aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornegrello2013-12-19 14:04:28 (EST)
committerSamuel Padgett2013-12-19 16:31:14 (EST)
commitb2137e6697920af700caf62027ba75603db9e2f2 (patch)
tree5cd911d4a92a9bf904e94d2fa6d691b1f6b088a6
parentf6b01ac1aa9e172d68ba1cccf75cb74a59215dd6 (diff)
downloadorg.eclipse.lyo.core-b2137e6697920af700caf62027ba75603db9e2f2.zip
org.eclipse.lyo.core-b2137e6697920af700caf62027ba75603db9e2f2.tar.gz
org.eclipse.lyo.core-b2137e6697920af700caf62027ba75603db9e2f2.tar.bz2
Bug 424478: Test if candidate root references itself before discardingrefs/changes/72/20072/3
Change-Id: I0f0e8087dae0bcc448be5d0c6866357d2e6ba8e7 Signed-off-by: negrello <fnegre@br.ibm.com>
-rw-r--r--org.eclipse.lyo.oslc4j.provider.jena/src/main/java/org/eclipse/lyo/oslc4j/provider/jena/RdfXmlAbbreviatedWriter.java84
-rw-r--r--org.eclipse.lyo.oslc4j.provider.jena/src/test/java/org/eclipse/lyo/oslc4j/provider/jena/test/RdfXmlAbbreviatedWriterTest.java143
2 files changed, 215 insertions, 12 deletions
diff --git a/org.eclipse.lyo.oslc4j.provider.jena/src/main/java/org/eclipse/lyo/oslc4j/provider/jena/RdfXmlAbbreviatedWriter.java b/org.eclipse.lyo.oslc4j.provider.jena/src/main/java/org/eclipse/lyo/oslc4j/provider/jena/RdfXmlAbbreviatedWriter.java
index a8b06bd..44d59a2 100644
--- a/org.eclipse.lyo.oslc4j.provider.jena/src/main/java/org/eclipse/lyo/oslc4j/provider/jena/RdfXmlAbbreviatedWriter.java
+++ b/org.eclipse.lyo.oslc4j.provider.jena/src/main/java/org/eclipse/lyo/oslc4j/provider/jena/RdfXmlAbbreviatedWriter.java
@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.logging.Level;
import java.util.logging.Logger;
import com.hp.hpl.jena.rdf.model.AnonId;
@@ -349,17 +350,29 @@ public class RdfXmlAbbreviatedWriter implements RDFWriter {
rootTestAgainst.addAll(rootResources);
rootTestAgainst.addAll(objects);
for (Resource rootCandidate: rootResources) {
- logger.finest("validating root candidate: " + rootCandidate.toString());
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.finest("validating root candidate: " + rootCandidate.toString());
+ }
for (Resource rootTest: rootTestAgainst){
- logger.finest("testing against resource: " + rootTest.toString());
- if (!rootTest.equals(rootCandidate)) {
- boolean rootCandidateIsObject = model.listStatements(rootTest,null,rootCandidate).hasNext();
- boolean objectIsReification = model.listStatements(rootTest,RDF.type,RDF.Statement).hasNext();
- if (rootCandidateIsObject && !objectIsReification) {
- removalCandidates.add(rootCandidate);
- logger.finest("removed: " + rootCandidate.toString());
- }
- }
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.finest("testing against resource: " + rootTest.toString());
+ }
+ if (!rootTest.equals(rootCandidate)) {
+ boolean rootCandidateIsObject = model.listStatements(rootTest, null, rootCandidate).hasNext();
+ if (rootCandidateIsObject) {
+ boolean objectIsReification = model.listStatements(rootTest, RDF.type, RDF.Statement).hasNext();
+ if (!objectIsReification) {
+ // checks if there is a self cyclic reference for the resource.
+ boolean isCyclic = isChild(model, new HashSet<Resource>(), rootCandidate, rootCandidate);
+ if (!isCyclic) {
+ removalCandidates.add(rootCandidate);
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.finest("removed: " + rootCandidate.toString());
+ }
+ }
+ }
+ }
+ }
}
}
@@ -431,7 +444,56 @@ public class RdfXmlAbbreviatedWriter implements RDFWriter {
xmlWriter.end();
}
-
+
+ /**
+ * Returns true if there is a path leading from <code>parent</code> to any
+ * of the resources in <code>children</code>.
+ *
+ * @param model
+ * model.
+ * @param visitedResources
+ * resource already visited during the search.
+ * @param parent
+ * parent resource.
+ * @param children
+ * children resources.
+ * @return true if there is a path.
+ */
+ private boolean isChild(Model model, Set<Resource> visitedResources, Resource parent, Resource... children) {
+ boolean isChild = false;
+ List<Resource> newChildren = new ArrayList<Resource>();
+ outer: for (Resource child : children)
+ {
+ visitedResources.add(child);
+ List<Statement> list = model.listStatements(null, null, child).toList();
+ for (Statement stat : list)
+ {
+ RDFNode subject = stat.getSubject();
+ if (subject.isResource())
+ {
+ Resource subjectAsResource = subject.asResource();
+ if (subject.equals(parent))
+ {
+ isChild = true;
+ break outer;
+ }
+ else {
+ if (!visitedResources.contains(subjectAsResource))
+ {
+ newChildren.add(subjectAsResource);
+ }
+ }
+ }
+ }
+ }
+ if (!isChild && newChildren.size() > 0)
+ {
+ Resource[] childrenResources = new Resource[newChildren.size()];
+ isChild = isChild(model, visitedResources, parent, (Resource[]) newChildren.toArray(childrenResources));
+ }
+ return isChild;
+ }
+
private void serializeStatements(Resource resource, XMLWriter xmlWriter, List<Resource> serializedResources, String rootResourceTypeURI){
StmtIterator statementIterator = resource.getModel().listStatements(resource, null, ((RDFNode)(null)));
diff --git a/org.eclipse.lyo.oslc4j.provider.jena/src/test/java/org/eclipse/lyo/oslc4j/provider/jena/test/RdfXmlAbbreviatedWriterTest.java b/org.eclipse.lyo.oslc4j.provider.jena/src/test/java/org/eclipse/lyo/oslc4j/provider/jena/test/RdfXmlAbbreviatedWriterTest.java
index b4d64b2..8b360fc 100644
--- a/org.eclipse.lyo.oslc4j.provider.jena/src/test/java/org/eclipse/lyo/oslc4j/provider/jena/test/RdfXmlAbbreviatedWriterTest.java
+++ b/org.eclipse.lyo.oslc4j.provider.jena/src/test/java/org/eclipse/lyo/oslc4j/provider/jena/test/RdfXmlAbbreviatedWriterTest.java
@@ -15,10 +15,55 @@
*******************************************************************************/
package org.eclipse.lyo.oslc4j.provider.jena.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+
+import junit.framework.Assert;
+
+import org.eclipse.lyo.oslc4j.core.model.QueryCapability;
+import org.eclipse.lyo.oslc4j.core.model.ResponseInfo;
+import org.eclipse.lyo.oslc4j.core.model.ResponseInfoCollection;
+import org.eclipse.lyo.oslc4j.core.model.Service;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.oslc4j.provider.jena.AbstractOslcRdfXmlProvider;
+import org.eclipse.lyo.oslc4j.provider.jena.OslcRdfXmlCollectionProvider;
+import org.eclipse.lyo.oslc4j.provider.jena.OslcRdfXmlProvider;
import org.eclipse.lyo.oslc4j.provider.jena.RdfXmlAbbreviatedWriter;
import org.junit.Test;
@@ -36,4 +81,100 @@ public class RdfXmlAbbreviatedWriterTest {
RdfXmlAbbreviatedWriter w = new RdfXmlAbbreviatedWriter();
w.write(m, System.out, null);
}
+
+ /**
+ * Scenario tested with cyclic reference http://server/oslc/pr/collection:
+ * {@code
+ * <rdf:RDF>
+ * <rdfs:Container rdf:about = "http://server/oslc/pr/collection">
+ * <rdfs:member>
+ * <oslc:ServiceProvider rdf:about = "http://test:9999/inlineResources/self-circular.xml">
+ * <oslc:service>
+ * <oslc:Service>
+ * <oslc:queryCapability>
+ * <oslc:QueryCapability>
+ * <oslc:queryBase rdf:resource = "http://server/oslc/pr/collection"/>
+ * </oslc:QueryCapability>
+ * </oslc:queryCapability>
+ * </oslc:Service>
+ * </oslc:service>
+ * </oslc:ServiceProvider>
+ * </rdfs:member>
+ * </rdfs:Container>
+ * </rdf:RDF>
+ * }
+ */
+ @Test
+ public void testSelfCircularReference() throws WebApplicationException, IOException, SecurityException,
+ NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+
+ // Cannot read a payload with this scenario because the reader will define
+ // the collection as an inline resource, preventing the bug we want to test.
+
+ ServiceProvider sp = new ServiceProvider();
+ sp.setAbout(URI.create("http://test:9999/inlineResources/self-circular.xml"));
+ Service service = new Service();
+ sp.addService(service);
+ QueryCapability queryCapability = new QueryCapability();
+ service.addQueryCapability(queryCapability);
+ queryCapability.setQueryBase(URI.create("http://server/pr/collection"));
+
+ List<ServiceProvider> list = new ArrayList<ServiceProvider>(1);
+ list.add(sp);
+
+ ResponseInfoCollection<ServiceProvider> info = new ResponseInfoCollection<ServiceProvider>(list, null, 1,
+ (String) null);
+ info.setAbout(URI.create("http://server/pr/collection?oslc.select=*"));
+ info.getContainer().setAbout(URI.create("http://server/pr/collection"));
+
+ // Since we do not have a Mock API, creating a proxy to mock the
+ // request.
+ HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance(
+ HttpServletRequest.class.getClassLoader(), new Class<?>[] { HttpServletRequest.class },
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
+ if (arg1.getReturnType().isPrimitive()) {
+ return 0;
+ }
+ return null;
+ }
+ });
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OslcRdfXmlProvider op = new OslcRdfXmlProvider();
+ Field requestURIField = AbstractOslcRdfXmlProvider.class.getDeclaredField("httpServletRequest");
+ requestURIField.setAccessible(true);
+ requestURIField.set(op, proxy);
+ op.writeTo(info, ResponseInfo.class, ServiceProvider.class, null, MediaType.APPLICATION_XML_TYPE, null, baos);
+
+ ParameterizedType paramType = new ParameterizedType() {
+
+ @Override
+ public Type getRawType() {
+ return List.class;
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return null;
+ }
+
+ @Override
+ public Type[] getActualTypeArguments() {
+
+ return new Type[] { ServiceProvider.class };
+ }
+ };
+
+ System.out.println(baos.toString());
+
+ OslcRdfXmlCollectionProvider ocp = new OslcRdfXmlCollectionProvider();
+ Collection col = ocp.readFrom((Class) List.class, paramType, null, MediaType.APPLICATION_XML_TYPE, null,
+ new ByteArrayInputStream(baos.toByteArray()));
+
+ Assert.assertEquals("Unable to read a collection with cyclic reference", 1, col.size());
+
+ }
+
}