You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by re...@apache.org on 2013/06/26 11:29:21 UTC

svn commit: r1496856 - in /stanbol/branches/commons-ng/commons: ./ indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/ indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/ namespaceprefix/prefixccprovider/src/main/java/or...

Author: reto
Date: Wed Jun 26 09:29:20 2013
New Revision: 1496856

URL: http://svn.apache.org/r1496856
Log:
STANBOL-1097: merged down commons

Modified:
    stanbol/branches/commons-ng/commons/   (props changed)
    stanbol/branches/commons-ng/commons/indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/IndexedTripleCollection.java
    stanbol/branches/commons-ng/commons/indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/IndexedGraphTest.java
    stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/main/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProvider.java
    stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/test/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProviderTest.java
    stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/editUser.ftl
    stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/permissionsCheckboxes.ftl
    stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/RegisteredSolrServerTracker.java
    stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/SolrServerAdapter.java
    stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/utils/SolrUtil.java
    stanbol/branches/commons-ng/commons/web/base.jersey/src/main/java/org/apache/stanbol/commons/web/base/jersey/JerseyEndpoint.java
    stanbol/branches/commons-ng/commons/web/home/src/license/THIRD-PARTY.properties
    stanbol/branches/commons-ng/commons/web/home/src/main/resources/META-INF/resources/static/home/style/stanbol.css
    stanbol/branches/commons-ng/commons/web/viewable-writer/src/main/java/org/apache/stanbol/commons/viewable/writer/impl/ViewableWriter.java

Propchange: stanbol/branches/commons-ng/commons/
------------------------------------------------------------------------------
  Merged /stanbol/trunk/commons:r1490394-1496831

Modified: stanbol/branches/commons-ng/commons/indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/IndexedTripleCollection.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/IndexedTripleCollection.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/IndexedTripleCollection.java (original)
+++ stanbol/branches/commons-ng/commons/indexedgraph/src/main/java/org/apache/stanbol/commons/indexedgraph/IndexedTripleCollection.java Wed Jun 26 09:29:20 2013
@@ -19,19 +19,26 @@ package org.apache.stanbol.commons.index
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.NavigableSet;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
 import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.Language;
+import org.apache.clerezza.rdf.core.Literal;
 import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
 import org.apache.clerezza.rdf.core.Resource;
 import org.apache.clerezza.rdf.core.Triple;
 import org.apache.clerezza.rdf.core.TripleCollection;
+import org.apache.clerezza.rdf.core.TypedLiteral;
 import org.apache.clerezza.rdf.core.UriRef;
 import org.apache.clerezza.rdf.core.impl.AbstractTripleCollection;
 import org.apache.clerezza.rdf.core.impl.TripleImpl;
@@ -162,8 +169,10 @@ class IndexedTripleCollection extends Ab
     public IndexedTripleCollection(Collection<Triple> baseCollection) {
         super();
         spo.addAll(baseCollection);
-        pos.addAll(baseCollection);
-        osp.addAll(baseCollection);
+        //use internal index to fill the other indexes, because the parsed
+        //collection might be slow
+        pos.addAll(spo); 
+        osp.addAll(spo);
     }
     
     @Override
@@ -271,65 +280,187 @@ class IndexedTripleCollection extends Ab
             return Integer.MAX_VALUE;
         };
     };
-    
+
+//    /**
+//     * Compares two resources with special support for {@link #MIN} and
+//     * {@link #MAX} to allow building {@link SortedSet#subSet(Object, Object)}
+//     * for <code>null</code> values parsed to 
+//     * {@link #filter(NonLiteral, UriRef, Resource)}
+//     * @param a
+//     * @param b
+//     * @return
+//     */
+//    protected static int compareHash(Resource a, Resource b, Map<Integer,List<Resource>> confictsMap) {
+//        int hashA = a.hashCode();
+//        int hashB = b.hashCode();
+//        if (hashA != hashB) {
+//            return hashA > hashB ? 1 : -1;
+//        }
+//        //those resources might be equals
+//        //(1) Check for MIN, MAX (used to build sub-sets). Other resources might
+//        //    have a similar hasCode
+//        int state = a == MIN || b == MAX ? -1 :
+//            a == MAX || b == MIN ? 1 : 0;
+//        if(state == 0){
+//            if(a.equals(b)){ //check of the resources are equals
+//                return 0; //return zero
+//            } else if(//we need to care about HashCode conflicts 
+//                a instanceof BNode && b instanceof BNode){ // of BNodes
+//                log.info("HashCode conflict for {} and {}",a,b); //we have a conflict
+//                return resolveBNodeHashConflict(a, b, confictsMap);
+//            } else { //same hashCode but not equals
+//                //use the String representation of the Resources to sort them
+//                String as = resource2String(a);
+//                String bs = resource2String(b);
+//                log.info("same hash code {} - compare Strings a: {}, b: {}",
+//                    new Object[]{a.hashCode(),as,bs});
+//                return as.compareTo(bs);
+//            }
+//        }
+//       return state;
+//    }
 
     /**
-     * Compares two resources with special support for {@link #MIN} and
-     * {@link #MAX} to allow building {@link SortedSet#subSet(Object, Object)}
-     * for <code>null</code> values parsed to 
-     * {@link #filter(NonLiteral, UriRef, Resource)}
-     * @param a
-     * @param b
-     * @return
-     */
-    protected static int compare(Resource a, Resource b, Map<Integer,List<Resource>> confictsMap) {
-        int hashA = a.hashCode();
-        int hashB = b.hashCode();
-        if (hashA != hashB) {
-            return hashA > hashB ? 1 : -1;
-        }
-        int state = a == MIN || b == MAX ? -1 :
-            a == MAX || b == MIN ? 1 : a.toString().compareTo(b.toString());
-        if(state == 0 && //same string representation -> should be equals
-                a instanceof BNode && //but for BNodes it might be a hashcode conflict
-                !a.equals(b)){ //so check if they are not equals
-            log.info("HashCode conflict for {} and {}",a,b); //we have a conflict
-            //This is not a bad thing. We need just to ensure constant ordering
-            //and as there is nothing we can use to distinguish we need to keep
-            //this information in a list.
-            Integer hash = Integer.valueOf(a.hashCode());
-            List<Resource> resources = confictsMap.get(hash);
-            if(resources == null){ //new conflict ... just add and return
-                resources = new ArrayList<Resource>(2);
-                confictsMap.put(hash, resources);
-                resources.add(a);
-                resources.add(b);
-                return -1;
+     * Resolved BNode hasConflics, by storing the correct order for the affected
+     * {@link Integer} in a {@link List} of Resource instances.
+     * @param a the first {@link BNode}
+     * @param b the second {@link BNode}
+     * @param confictsMap the Map used to store the order of BNodes with conflicts
+     * @return the decision taken based on the confictsMap.
+     */
+    private static int resolveBNodeHashConflict(Resource a, Resource b,
+            Map<Integer,List<Resource>> confictsMap) {
+        //This is not a bad thing. We need just to ensure constant ordering
+        //and as there is nothing we can use to distinguish we need to keep
+        //this information in a list.
+        Integer hash = Integer.valueOf(a.hashCode());
+        List<Resource> resources = confictsMap.get(hash);
+        if(resources == null){ //new conflict ... just add and return
+            resources = new ArrayList<Resource>(2);
+            confictsMap.put(hash, resources);
+            resources.add(a);
+            resources.add(b);
+            return -1;
+        }
+        //already conflicting resource for this hash present
+        int aIndex=-1;
+        int bIndex=-1;
+        for(int i = 0; i<resources.size() && (aIndex < 0 || bIndex < 0);i++){
+            Resource r = resources.get(i);
+            if(aIndex < 0 && r.equals(a)){
+                aIndex = i;
             }
-            //already conflicting resource for this hash present
-            int aIndex=-1;
-            int bIndex=-1;
-            for(int i = 0; i<resources.size() && (aIndex < 0 || bIndex < 0);i++){
-                Resource r = resources.get(i);
-                if(aIndex < 0 && r.equals(a)){
-                    aIndex = i;
+            if(bIndex < 0 && r.equals(b)){
+                bIndex = i;
+            }
+        }
+        if(aIndex < 0){ //a not found
+            aIndex = resources.size();
+            resources.add(a);
+        }
+        if(bIndex < 0){ //b not found
+            bIndex = resources.size();
+            resources.add(b);
+        }
+        return aIndex < bIndex ? -1 : 1;
+    }
+    /**
+     * Compares Resources to correctly sort them within the index.<p>
+     * Sort criteria are:<ol>
+     * <li> URIs are sorted by the {@link UriRef#getUnicodeString()} unicode string)
+     * <li> Literals 
+     *  <ol>
+     *      <li> sort by the {@link Literal#getLexicalForm() lixical form}
+     *      <li> sort by {@link PlainLiteral#getLanguage() language} (<code>null</code> value first)
+     *      <li> sort by {@link TypedLiteral#getDataType() type} (<code>null</code> value fist
+     *  </ol>
+     * <li> BNode 
+     *  <ol>
+     *      <li> sorted by their {@link System#identityHashCode(Object) Object hasCode}
+     *      <li> on hasCode conflicts (same hasCode but not equals) a random order is chosen
+     *      and kept in the parsed conflictsMap
+     *  </ol> 
+     * </ol>
+     * <b>NOTEs</b><ul>
+     * <li> parsed {@link Resource} are not required to correctly implement 
+     * {@link Object#hashCode() hashCode} and {@link Object#equals(Object) equals}
+     * <li> parsed {@link UriRef} and {@link BNode} and {@link Literal} MUST NOT
+     * extend/implement any of the other classes/interfaces. This means that an
+     * {@link UriRef} MUST NOT implement {@link BNode} nor {@link Literal}
+     * <li> parsed {@link Literal}s MAY implement {@link PlainLiteral} AND
+     * {@link TypedLiteral}. This allows wrappers over frameworks that do not
+     * distinguish between those two literal types to be used with the
+     * {@link IndexedTripleCollection}.
+     * </ul>
+     * 
+     * @param a the first resource to compare
+     * @param b the second resource to compare
+     * @param confictsMap the map used to resolve BNodes with hasCode conflicts 
+     * @return 
+     */
+    protected static int compare(Resource a, Resource b, Map<Integer,List<Resource>> confictsMap){
+        //Handle special cases for MAX and MIN values
+        if(a == MIN || b == MAX) {
+            return -1 ;
+        } else if(a == MAX || b == MIN){
+            return 1;
+        }
+        //sort (0) UriRefs < (1) Literals (PlainLiterals & TypedLiterals) < (3) BNodes
+        int at = a instanceof UriRef ? 0 : a instanceof Literal ? 1 : 2;
+        int bt = b instanceof UriRef ? 0 : b instanceof Literal ? 1 : 2;
+        if(at == bt){ //same type sort the different types
+            if(at < 2){ //no BNode
+                //sort in alphabetic order of the string representation
+                String as = at == 0 ? ((UriRef)a).getUnicodeString() :
+                    ((Literal)a).getLexicalForm();
+                String bs = bt == 0 ? ((UriRef)b).getUnicodeString() :
+                    ((Literal)b).getLexicalForm();
+                int sc = as.compareTo(bs);
+                if(sc == 0 && at == 1){ //same string value and Literals
+                    //check if the language and types are the same
+                    Language al = a instanceof PlainLiteral ? ((PlainLiteral)a).getLanguage() : null;
+                    Language bl = b instanceof PlainLiteral ? ((PlainLiteral)b).getLanguage() : null;
+                    //first try to sort by language
+                    if(al == null){
+                        sc = bl == null ? 0 : -1;
+                    } else if(bl == null){
+                        sc = 1;
+                    } else {
+                        sc = al.toString().compareTo(bl.toString());
+                    }
+                    if(sc == 0){
+                        //if still equals look at the dataType
+                        UriRef adt = a instanceof TypedLiteral ? ((TypedLiteral)a).getDataType() : null;
+                        UriRef bdt = b instanceof TypedLiteral ? ((TypedLiteral)b).getDataType() : null;
+                        if(adt == null){
+                            sc = bdt == null ? 0 : -1;
+                        } else if(bdt == null){
+                            sc = 1;
+                        } else {
+                            sc = adt.getUnicodeString().compareTo(bdt.getUnicodeString());
+                        }
+                    }
+                    return sc;
+                } else { //for UriRefs return the string compare
+                    return sc;
                 }
-                if(bIndex < 0 && r.equals(b)){
-                    bIndex = i;
+            } else { //handle BNodes
+                //sort BNodes based on hashCode
+                int ah = System.identityHashCode(a);
+                int bh = System.identityHashCode(b);
+                if(ah == bh){
+                    if(!a.equals(b)){
+                        return resolveBNodeHashConflict(a, b, confictsMap);
+                    } else { //same hash and equals
+                        return 0;
+                    }
+                } else { //sort by hash
+                    return ah < bh ? -1 : 1;
                 }
             }
-            if(aIndex < 0){ //a not found
-                aIndex = resources.size();
-                resources.add(a);
-            }
-            if(bIndex < 0){ //b not found
-                bIndex = resources.size();
-                resources.add(b);
-            }
-            return aIndex < bIndex ? -1 : 1;
-       } //no conflict or no conflict possible
-       return state;
+        } else {
+            return at < bt ? -1 : 1;
+        }
     }
-
     
 }

Modified: stanbol/branches/commons-ng/commons/indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/IndexedGraphTest.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/IndexedGraphTest.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/IndexedGraphTest.java (original)
+++ stanbol/branches/commons-ng/commons/indexedgraph/src/test/java/org/apache/stanbol/commons/indexedgraph/IndexedGraphTest.java Wed Jun 26 09:29:20 2013
@@ -17,8 +17,10 @@
 package org.apache.stanbol.commons.indexedgraph;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.ConcurrentModificationException;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -173,14 +175,19 @@ public class IndexedGraphTest  extends M
     @Test
     public void testPerformance(){
         //Reduced values to fix STANBOL-
-        MGraph sg = new SimpleMGraph();
+        Set<Triple> graph = new HashSet<Triple>();
         int iterations = 100; //reduced from 1000
         int graphsize = 100000;
         Long seed = System.currentTimeMillis();
         log.info("Test Seed: {}",seed);
-        createGraph(sg, graphsize, seed);
-        MGraph ig = new IndexedMGraph(sg);
-        long start;
+        createGraph(graph, graphsize, seed);
+        log.info("Load Time ({} triples)", graph.size());
+        long start = System.currentTimeMillis();
+        MGraph sg = new SimpleMGraph(graph);
+        log.info("  ... {}: {}",sg.getClass().getSimpleName(), System.currentTimeMillis()-start);
+        start = System.currentTimeMillis();
+        MGraph ig = new IndexedMGraph(graph);
+        log.info("  ... {}: {}",ig.getClass().getSimpleName(), System.currentTimeMillis()-start);
         //Simple Graph reference test
         TestCase testCase = new TestCase(sg, 20, 5, 20); //reduced form 100,5,100
         log.info("Filter Performance Test (graph size {} triples, iterations {})",graphsize,iterations);
@@ -365,7 +372,7 @@ public class IndexedGraphTest  extends M
         return count;
     }
     
-    private static void createGraph(TripleCollection tc, int triples, Long seed){
+    private static void createGraph(Collection<Triple> tc, int triples, Long seed){
         Random rnd = new Random();
         if(seed != null){
              rnd.setSeed(seed);

Modified: stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/main/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProvider.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/main/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProvider.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/main/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProvider.java (original)
+++ stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/main/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProvider.java Wed Jun 26 09:29:20 2013
@@ -17,18 +17,18 @@
 package org.apache.stanbol.commons.namespaceprefix.provider.prefixcc;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Date;
 import java.util.List;
 import java.util.ServiceLoader;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixProvider;
 import org.apache.stanbol.commons.namespaceprefix.impl.NamespacePrefixProviderImpl;
 import org.slf4j.Logger;
@@ -112,9 +112,26 @@ public class PrefixccProvider implements
     protected final void loadMappings() {
         try {
             log.info("Load Namespace Prefix Mappings form {}",GET_ALL);
-            cache = new NamespacePrefixProviderImpl(GET_ALL.openStream());
-            cacheStamp = System.currentTimeMillis();
-            log.info("  ... completed");
+            HttpURLConnection con = (HttpURLConnection)GET_ALL.openConnection();
+            con.setReadTimeout(5000); //set the max connect & read timeout to 5sec
+            con.setConnectTimeout(5000);
+            con.connect();
+            String contentType = con.getContentType();
+            if("text/plain".equalsIgnoreCase(contentType)){
+                InputStream in = con.getInputStream();
+                try {
+                    cache = new NamespacePrefixProviderImpl(in);
+                    cacheStamp = System.currentTimeMillis();
+                    log.info("  ... completed");
+                } finally {
+                    IOUtils.closeQuietly(in);
+                }
+            } else {
+                log.warn("Response from prefix.cc does have the wrong content type '"
+                    + contentType + "' (expected: text/plain). This indicates that the "
+                    + "service is currently unavailable!");
+            }
+            con.disconnect(); //we connect once every {long-period}
         } catch (IOException e) {
             log.warn("Unable to load prefix.cc NamespaceMappings (Message: "
                 + e.getMessage() +")",e);

Modified: stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/test/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProviderTest.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/test/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProviderTest.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/test/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProviderTest.java (original)
+++ stanbol/branches/commons-ng/commons/namespaceprefix/prefixccprovider/src/test/java/org/apache/stanbol/commons/namespaceprefix/provider/prefixcc/PrefixccProviderTest.java Wed Jun 26 09:29:20 2013
@@ -19,15 +19,16 @@ package org.apache.stanbol.commons.names
 
 import java.io.File;
 import java.io.IOException;
+import java.net.HttpURLConnection;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixService;
 import org.apache.stanbol.commons.namespaceprefix.service.StanbolNamespacePrefixService;
 import org.junit.Assert;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,18 +67,41 @@ public class PrefixccProviderTest {
         Assert.assertFalse(pcp.isAvailable());
         Assert.assertNull(pcp.getCacheTimeStamp());
     }
+    /**
+     * Checks if the service is reachable (test is performed online) and if
+     * prefix.cc sends information with the correct content type.
+     * @return
+     */
+    private boolean checkServiceAvailable(){
+        try {
+            HttpURLConnection con = (HttpURLConnection)PrefixccProvider.GET_ALL.openConnection();
+            con.setReadTimeout(5000); //set the max connect & read timeout to 5sec
+            con.setConnectTimeout(5000);
+            con.connect();
+            String contentType = con.getContentType();
+            IOUtils.closeQuietly(con.getInputStream()); //close the stream
+            if("text/plain".equalsIgnoreCase(contentType)){
+                return true;
+            } else {
+                log.info("Request to http://prefix.cc ... returned an unexpected "
+                        + "ContentType "+contentType+ " (expected: text/plain) "
+                        + " ... deactivate" + PrefixccProvider.class.getSimpleName() 
+                        + " test");
+                return false; //service seams to be down ... skip tests
+            }
+        } catch (IOException e) {
+           log.info("Unable to connect to http://prefix.cc ... deactivating "
+               + PrefixccProvider.class.getSimpleName()+ " test");
+           return false;
+        }
+    }
     
     @Test
     public void testServiceLoader() throws IOException{
         //this test works only if online
-        try {
-            PrefixccProvider.GET_ALL.openStream();
-        } catch (IOException e) {
-           log.info("Unable to connect to http://prefix.cc ... deactivating "
-               + PrefixccProvider.class.getSimpleName()+ "ServiceLoader support test");
-           return;
+        if(!checkServiceAvailable()){
+            return; //skip test
         }
-        
         //this test for now does not use predefined mappings
         
         URL mappingURL = PrefixccProviderTest.class.getClassLoader()

Modified: stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/editUser.ftl
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/editUser.ftl?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/editUser.ftl (original)
+++ stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/editUser.ftl Wed Jun 26 09:29:20 2013
@@ -54,7 +54,7 @@ limitations under the License.
          </fieldset> 
     
     <fieldset class="labelCheckbox">
-        <legend>Permissions!</legend>
+        <legend>Permissions</legend>
         <div id="permissions-checkboxes">
             <#include "permissionsCheckboxes.ftl">
         </div>

Modified: stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/permissionsCheckboxes.ftl
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/permissionsCheckboxes.ftl?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/permissionsCheckboxes.ftl (original)
+++ stanbol/branches/commons-ng/commons/security/usermanagement/src/main/resources/templates/html/org/apache/stanbol/commons/usermanagement/resource/permissionsCheckboxes.ftl Wed Jun 26 09:29:20 2013
@@ -10,8 +10,8 @@
     <@ldpath path="permission:javaPermissionEntry :: xsd:string"/>
     </#assign>
     <div class="role">
-        <input class="checkboxPermission" type="checkbox" id="${permission}" name="${permission}" value="${permission}" checked="checked"  />
-        <label for="${permission}">${permission}</label>
+        <input class="checkboxPermission" type="checkbox" id="${permission?html}" name="${permission?html}" value="${permission?html}" checked="checked"  />
+        <label for="${permission?html}">${permission?html}</label>
     </div>
     
 </...@ldpath>

Modified: stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/RegisteredSolrServerTracker.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/RegisteredSolrServerTracker.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/RegisteredSolrServerTracker.java (original)
+++ stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/RegisteredSolrServerTracker.java Wed Jun 26 09:29:20 2013
@@ -141,12 +141,12 @@ public class RegisteredSolrServerTracker
                 return null;
             }
             coreName = core.getName();
-            CoreDescriptor descriptior = core.getCoreDescriptor();
-            if(descriptior == null){ //core not registered with a container!
+            CoreDescriptor descriptor = core.getCoreDescriptor();
+            if(descriptor == null){ //core not registered with a container!
                 context.ungetService(reference);
                 return null; //ignore
             } else {
-                server = descriptior.getCoreContainer();
+                server = descriptor.getCoreContainer();
             }
         } else {
             if(service instanceof CoreContainer){ 

Modified: stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/SolrServerAdapter.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/SolrServerAdapter.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/SolrServerAdapter.java (original)
+++ stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/SolrServerAdapter.java Wed Jun 26 09:29:20 2013
@@ -158,27 +158,36 @@ public class SolrServerAdapter {
         
         @Override
         public void preClose(SolrCore core) {
+            log.debug("  ... in preClose SolrCore {}", core.getName());
             Collection<String> names = server.getCoreNames(core);
             if(names != null){
                 synchronized (registrations) {
                     for(String name : names){
                         CoreRegistration coreRegistration = registrations.get(name);
                         //we need to check if the core registered for the 
-                        //parsed name is still the same as parsed 
-                        if(coreRegistration.getCore().equals(core)){
-                            log.info("unregister Core with name '{}' based on call to" +
-                                " CloseHook#close()",name);
-                            registrations.remove(name);
-                            coreRegistration.unregister();
-                        } else {
-                            log.info("Core registered for name '{}' is not the same as" +
-                                    " parsed to CloseHook#close()",name);
-                        }
+                        //parsed name is still the same as parsed
+                        if(coreRegistration != null){
+                            if(coreRegistration.getCore().equals(core)){
+                                log.info("unregister Core with name '{}' based on call to" +
+                                    " CloseHook#close()",name);
+                                CoreRegistration removed = registrations.remove(name);
+                                if(removed != null){
+                                    removed.unregister();
+                                } //else removed in the meantime by an other thread ... nothing to do
+                            } else {
+                                log.info("Core registered for name '{}' is not the same as" +
+                                        " parsed to CloseHook#close()",name);
+                            }
+                        } //else the core was removed by using the API of the SolrServerAdapter
                     }
                 }
             }
             //update the OSGI service for the CoreContainer
-            updateServerRegistration();
+            try {
+                updateServerRegistration();
+            } catch (IllegalStateException e) {
+                log.debug("Server Registration already unregistered ",e);
+            }
         }
 
         @Override
@@ -218,100 +227,16 @@ public class SolrServerAdapter {
         this.context = context;
         //create a clone so that only we control who changes to the properties
         serverProperties = parsedServerProperties.clone();
-        SolrResourceLoader loader = new OsgiSolrResourceLoader(context, solrDir.getAbsolutePath(), 
-            SolrServerAdapter.class.getClassLoader());
 
-        //We need to override some methods of the CoreContainer to
-        // (1) ensure the OsigSolrResourceLoader is used
-        // (2) update the OSGI service registrations
-        //Previously this was done in the SolrServerAdapter, but to also support
-        //ReferencedSolrServer (STANBOL-1081) we do it now directly for the
-        //CoreContainer. This allows also to correctly load and register
-        //cores that are created/changed via the Solr RESTful API
-        CoreContainer container = new CoreContainer(loader){
-            //override this to ensure that the OsgiSolrResourceLodaer is used
-            //to create SolrCores
-            @Override
-            public SolrCore create(CoreDescriptor dcore) {
-                log.info(" .... createCore {}:{}",serverProperties.getServerName(),dcore.getName());
-                if (getZkController() != null) {
-                    //TODO: add support for ZooKeeper managed cores
-                    return super.create(dcore);
-                } else {
-                    File idir = new File(dcore.getInstanceDir());
-                    String instanceDir = idir.getPath();
-                    //TODO: we can not use the indexSchemaCache because it is 
-                    //      a private variable
-                    SolrResourceLoader loader = new OsgiSolrResourceLoader(context, instanceDir, 
-                        CoreContainer.class.getClassLoader());
-                    SolrConfig config;
-                    try {
-                        config = new SolrConfig(loader, dcore.getConfigName(), null);
-                    } catch (Exception e) {
-                        throw new SolrException(ErrorCode.SERVER_ERROR, "Could not load config for " + dcore.getConfigName(), e);
-                    }
-                    IndexSchema schema = new IndexSchema(config,dcore.getSchemaName(),null);
-                    SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
-                    if (core.getUpdateHandler().getUpdateLog() != null) {
-                        // always kick off recovery if we are in standalone mode.
-                        core.getUpdateHandler().getUpdateLog().recoverFromLog();
-                    }
-                    return core;
-                }
-            }
-            //this ensures that a closeHook is added to registered cores
-            @Override
-            protected SolrCore registerCore(Map<String,SolrCore> whichCores, String name, SolrCore core,
-                    boolean returnPrevNotClosed) {
-                log.info(" .... registerCore {}:{}",serverProperties.getServerName(),name);
-                SolrCore old =  super.registerCore(whichCores, name, core, returnPrevNotClosed);
-                //NOTE: we can not register the services here, as this can trigger
-                //      a deadlock!!
-                //Reason: OSGI ensures that activation is done by a single thread.
-                //        Solr uses a Threadpool to activate SolrCores. This means
-                //        that this method is called in a different thread context 
-                //        as the OSGI activation thread. However the registration
-                //        of the SolrCore would try to re-sync on the OSGI activation
-                //        Thread and therefore cause a deadlock as the
-                //        constructor of the SolrServerAdapter is typically expected
-                //        to be called within an activate method.
-                //Solution: the 'initialised' switch is only set to TRUE after the
-                //          initialisation of the CoreContainer. During initialisation
-                //          the SolrCores ore only registered after the construction
-                //          of the CoreContainer. This ensures that the OSGI
-                //          activation thread context is used for registration
-                //          If SolrCores are registered afterwards (e.g a SolrCore
-                //          is added to a ManagedSolrServer) the registration is
-                //          done as part of this method (because 'initialised' is
-                //          already set to TRUE). 
-                if(initialised){ //already initialised ?
-                    //register the core as OSGI service
-                    registerCoreService(name, core);
-                    updateCoreNamesInServerProperties();
-                    updateServerRegistration();
-                    //add a closeHook so that we know when to unregister
-                    core.addCloseHook(closeHook);
-                } //else ignore registration during startup
-                return old;
-            }
-            //in the case of a swap we need to update the OSGI service registrations
-            @Override
-            public void swap(String name1, String name2) {
-                log.info(" .... swap {}:{} with {}:{}",new Object[]{
-                        serverProperties.getServerName(),name1,
-                        serverProperties.getServerName(),name2
-                });
-                super.swap(name1, name2);
-                //also update the OSGI Service registrations
-                if(initialised){
-                    registerCoreService(name1,null);
-                    registerCoreService(name2,null);
-                    //update the OSGI service for the CoreContainer
-                    updateCoreNamesInServerProperties();
-                    updateServerRegistration();
-                } //else ignore registration during startup
-            }
-        };
+        ClassLoader classLoader = updateContextClassLoader();
+        CoreContainer container;
+        try {
+            SolrResourceLoader loader = new OsgiSolrResourceLoader(context, solrDir.getAbsolutePath(), 
+                SolrServerAdapter.class.getClassLoader());
+            container = new OsgiCoreContainer(loader, context);
+        } finally {
+            Thread.currentThread().setContextClassLoader(classLoader);
+        }
         File solrCof = new File(solrDir,parsedServerProperties.getSolrXml());
         this.server = container;
         this.registrations = Collections.synchronizedMap(
@@ -322,7 +247,7 @@ public class SolrServerAdapter {
             serverProperties.setServerName(solrDir.getAbsolutePath());
         }
         //now load the cores
-        ClassLoader classLoader = updateContextClassLoader();
+        classLoader = updateContextClassLoader();
         try {
             log.info("    ... load SolrConfig {}",solrCof);
             container.load(solrDir.getAbsolutePath(), solrCof);
@@ -354,6 +279,7 @@ public class SolrServerAdapter {
      * this instance. This will also cause all OSGI services to be unregistered
      */
     public void shutdown(){
+        log.debug(" ... in shutdown for SolrServer {}",serverProperties.getServerName());
         Collection<CoreRegistration> coreRegistrations;
         synchronized (registrations) {
             coreRegistrations = new ArrayList<CoreRegistration>(registrations.values());
@@ -559,10 +485,11 @@ public class SolrServerAdapter {
         //the reference count of the SolrCore does not reach 0)
         CoreRegistration current = new CoreRegistration(name,core);
         CoreRegistration old = registrations.put(name,current);
+        log.info("added Registration for SolrCore {}",name);
         if(old != null){
+            log.info("  ... unregister old registration {}", old);
             old.unregister();
         }
-        log.info("added Registration for SolrCore {}",name);
         return current.getServiceReference();
     }
     
@@ -670,6 +597,109 @@ public class SolrServerAdapter {
         serverRegistration.setProperties(serverProperties);
     }
     /**
+     * We need to override some methods of the CoreContainer to
+     * (1) ensure the OsigSolrResourceLoader is used
+     * (2) update the OSGI service registrations
+     * Previously this was done in the SolrServerAdapter, but to also support
+     * ReferencedSolrServer (STANBOL-1081) we do it now directly for the
+     * CoreContainer. This allows also to correctly load and register
+     * cores that are created/changed via the Solr RESTful API
+     * @author Rupert Westenthaler
+     */
+    private final class OsgiCoreContainer extends CoreContainer {
+        private final BundleContext context;
+
+        private OsgiCoreContainer(SolrResourceLoader loader, BundleContext context) {
+            super(loader);
+            this.context = context;
+        }
+
+        //override this to ensure that the OsgiSolrResourceLodaer is used
+        //to create SolrCores
+        @Override
+        public SolrCore create(CoreDescriptor dcore) {
+            log.info(" .... createCore {}:{}",serverProperties.getServerName(),dcore.getName());
+            if (getZkController() != null) {
+                //TODO: add support for ZooKeeper managed cores
+                return super.create(dcore);
+            } else {
+                File idir = new File(dcore.getInstanceDir());
+                String instanceDir = idir.getPath();
+                //TODO: we can not use the indexSchemaCache because it is 
+                //      a private variable
+                SolrResourceLoader loader = new OsgiSolrResourceLoader(context, instanceDir, 
+                    CoreContainer.class.getClassLoader());
+                SolrConfig config;
+                try {
+                    config = new SolrConfig(loader, dcore.getConfigName(), null);
+                } catch (Exception e) {
+                    throw new SolrException(ErrorCode.SERVER_ERROR, "Could not load config for " + dcore.getConfigName(), e);
+                }
+                IndexSchema schema = new IndexSchema(config,dcore.getSchemaName(),null);
+                SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
+                if (core.getUpdateHandler().getUpdateLog() != null) {
+                    // always kick off recovery if we are in standalone mode.
+                    core.getUpdateHandler().getUpdateLog().recoverFromLog();
+                }
+                return core;
+            }
+        }
+
+        //this ensures that a closeHook is added to registered cores
+        @Override
+        protected SolrCore registerCore(Map<String,SolrCore> whichCores, String name, SolrCore core,
+                boolean returnPrevNotClosed) {
+            log.info(" .... registerCore {}:{}",serverProperties.getServerName(),name);
+            SolrCore old =  super.registerCore(whichCores, name, core, returnPrevNotClosed);
+            //NOTE: we can not register the services here, as this can trigger
+            //      a deadlock!!
+            //Reason: OSGI ensures that activation is done by a single thread.
+            //        Solr uses a Threadpool to activate SolrCores. This means
+            //        that this method is called in a different thread context 
+            //        as the OSGI activation thread. However the registration
+            //        of the SolrCore would try to re-sync on the OSGI activation
+            //        Thread and therefore cause a deadlock as the
+            //        constructor of the SolrServerAdapter is typically expected
+            //        to be called within an activate method.
+            //Solution: the 'initialised' switch is only set to TRUE after the
+            //          initialisation of the CoreContainer. During initialisation
+            //          the SolrCores ore only registered after the construction
+            //          of the CoreContainer. This ensures that the OSGI
+            //          activation thread context is used for registration
+            //          If SolrCores are registered afterwards (e.g a SolrCore
+            //          is added to a ManagedSolrServer) the registration is
+            //          done as part of this method (because 'initialised' is
+            //          already set to TRUE). 
+            if(initialised){ //already initialised ?
+                //register the core as OSGI service
+                registerCoreService(name, core);
+                updateCoreNamesInServerProperties();
+                updateServerRegistration();
+                //add a closeHook so that we know when to unregister
+                core.addCloseHook(closeHook);
+            } //else ignore registration during startup
+            return old;
+        }
+
+        //in the case of a swap we need to update the OSGI service registrations
+        @Override
+        public void swap(String name1, String name2) {
+            log.info(" .... swap {}:{} with {}:{}",new Object[]{
+                    serverProperties.getServerName(),name1,
+                    serverProperties.getServerName(),name2
+            });
+            super.swap(name1, name2);
+            //also update the OSGI Service registrations
+            if(initialised){
+                registerCoreService(name1,null);
+                registerCoreService(name2,null);
+                //update the OSGI service for the CoreContainer
+                updateCoreNamesInServerProperties();
+                updateServerRegistration();
+            } //else ignore registration during startup
+        }
+    }
+    /**
      * Internally used to manage the OSGI service registration for
      * {@link SolrCore}s of the {@link CoreContainer} managed by this
      * {@link SolrServerAdapter} instance
@@ -678,7 +708,7 @@ public class SolrServerAdapter {
      */
     private class CoreRegistration {
         protected final String name;
-        protected final SolrCore core;
+        protected SolrCore core;
         private ServiceRegistration registration;
         /**
          * Creates and registers a {@link CoreRegistration}
@@ -742,15 +772,26 @@ public class SolrServerAdapter {
                     registration = null;
                 }
             }
-            
             try {
-                tmp.unregister(); //unregister the service
-            } catch (IllegalStateException e) {
-                log.info(String.format(
-                    "Looks like that the registration for SolrCore %s was already unregisterd",
-                    name),e);
-            } finally {
-                core.close(); //close the core to decrease the refernece count!!
+                if(tmp != null){
+                    try {
+                        tmp.unregister(); //unregister the service
+                    } catch (IllegalStateException e) {
+                        log.info(String.format(
+                            "Looks like that the registration for SolrCore %s was already unregisterd",
+                            name),e);
+                    }
+                }
+            } finally { //ensure that the core is closed to decrease the reference count
+                //ensure this is only done once
+                SolrCore core;
+                synchronized (this) {
+                    core = this.core; //copy over to a local variable
+                    this.core = null; //set the field to null
+                }
+                if(core != null){
+                    core.close(); //decrease the reference count!!
+                }
             }
         }
         /**

Modified: stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/utils/SolrUtil.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/utils/SolrUtil.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/utils/SolrUtil.java (original)
+++ stanbol/branches/commons-ng/commons/solr/core/src/main/java/org/apache/stanbol/commons/solr/utils/SolrUtil.java Wed Jun 26 09:29:20 2013
@@ -21,9 +21,9 @@ import java.util.regex.Pattern;
 public final class SolrUtil {
     private SolrUtil() {}
 
-    private static final String LUCENE_ESCAPE_CHARS = "[\\\\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~\\*\\?\\\"]";
+    private static final String LUCENE_ESCAPE_CHARS = "[\\\\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~\\*\\?\\\"\\/]";
     private static final Pattern LUCENE_PATTERN = Pattern.compile(LUCENE_ESCAPE_CHARS);
-    private static final String WILDCARD_ESCAPE_CHARS = "[\\\\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~\\\"]";
+    private static final String WILDCARD_ESCAPE_CHARS = "[\\\\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~\\\"\\/]";
     private static final Pattern WILDCARD_PATTERN = Pattern.compile(WILDCARD_ESCAPE_CHARS);
     private static final String REPLACEMENT_STRING = "\\\\$0";
 

Modified: stanbol/branches/commons-ng/commons/web/base.jersey/src/main/java/org/apache/stanbol/commons/web/base/jersey/JerseyEndpoint.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/web/base.jersey/src/main/java/org/apache/stanbol/commons/web/base/jersey/JerseyEndpoint.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/web/base.jersey/src/main/java/org/apache/stanbol/commons/web/base/jersey/JerseyEndpoint.java (original)
+++ stanbol/branches/commons-ng/commons/web/base.jersey/src/main/java/org/apache/stanbol/commons/web/base/jersey/JerseyEndpoint.java Wed Jun 26 09:29:20 2013
@@ -271,6 +271,7 @@ public class JerseyEndpoint {
     protected void unbindWebFragment(WebFragment webFragment) throws IOException,
                                                              ServletException,
                                                              NamespaceException {
+        navigationLinks.removeAll(webFragment.getNavigationLinks());
         webFragments.remove(webFragment);
         initJersey();
     }

Modified: stanbol/branches/commons-ng/commons/web/home/src/license/THIRD-PARTY.properties
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/web/home/src/license/THIRD-PARTY.properties?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/web/home/src/license/THIRD-PARTY.properties (original)
+++ stanbol/branches/commons-ng/commons/web/home/src/license/THIRD-PARTY.properties Wed Jun 26 09:29:20 2013
@@ -20,8 +20,7 @@
 # Please fill the missing licenses for dependencies :
 #
 #
-#Thu Dec 13 13:43:20 CET 2012
-asm--asm--3.1=BSD License
+#Fri Mar 22 11:51:15 CET 2013
 javax.servlet--servlet-api--2.5=Common Development And Distribution License (CDDL), Version 1.0
 org.codehaus.jettison--jettison--1.3=The Apache Software License, Version 2.0
 org.osgi--org.osgi.compendium--4.1.0=The Apache Software License, Version 2.0

Modified: stanbol/branches/commons-ng/commons/web/home/src/main/resources/META-INF/resources/static/home/style/stanbol.css
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/web/home/src/main/resources/META-INF/resources/static/home/style/stanbol.css?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/web/home/src/main/resources/META-INF/resources/static/home/style/stanbol.css (original)
+++ stanbol/branches/commons-ng/commons/web/home/src/main/resources/META-INF/resources/static/home/style/stanbol.css Wed Jun 26 09:29:20 2013
@@ -445,3 +445,15 @@ p.note {
   text-align: center;
   font-size: 110%;
 }
+
+div.enginelisting span.active {
+  color: #006600;
+}
+
+div.enginelisting span.optional {
+  color: #666666;
+}
+
+div.enginelisting span.inactive {
+  color: #660000;
+}

Modified: stanbol/branches/commons-ng/commons/web/viewable-writer/src/main/java/org/apache/stanbol/commons/viewable/writer/impl/ViewableWriter.java
URL: http://svn.apache.org/viewvc/stanbol/branches/commons-ng/commons/web/viewable-writer/src/main/java/org/apache/stanbol/commons/viewable/writer/impl/ViewableWriter.java?rev=1496856&r1=1496855&r2=1496856&view=diff
==============================================================================
--- stanbol/branches/commons-ng/commons/web/viewable-writer/src/main/java/org/apache/stanbol/commons/viewable/writer/impl/ViewableWriter.java (original)
+++ stanbol/branches/commons-ng/commons/web/viewable-writer/src/main/java/org/apache/stanbol/commons/viewable/writer/impl/ViewableWriter.java Wed Jun 26 09:29:20 2013
@@ -103,7 +103,9 @@ public class ViewableWriter implements M
             freemarker.getTemplate(templatePath).process(pojo, out);
             out.flush();
         } catch (IOException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("IOException while processing Template '"
+                + templatePath + "' with Object '"+pojo+"' (class: "
+                + pojo != null ? pojo.getClass().getName() : null + ")!",e);
         } catch (TemplateException e) {
             throw new RuntimeException(e);
         }