001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.http.commons.test.util; 019 020import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel; 021import static java.net.URI.create; 022import static javax.ws.rs.core.UriBuilder.fromUri; 023import static org.junit.Assert.assertNotNull; 024import static org.apache.jena.riot.RDFLanguages.contentTypeToLang; 025import static org.fcrepo.kernel.api.utils.ContentDigest.asURI; 026import static org.mockito.Matchers.anyString; 027import static org.mockito.Mockito.mock; 028import static org.mockito.Mockito.when; 029 030import java.io.IOException; 031import java.io.InputStream; 032import java.lang.reflect.Field; 033import java.net.URI; 034import java.security.MessageDigest; 035import java.security.NoSuchAlgorithmException; 036import java.security.Principal; 037import java.util.Arrays; 038import java.util.Collection; 039import java.util.Date; 040 041import javax.jcr.LoginException; 042import javax.jcr.Node; 043import javax.jcr.NodeIterator; 044import javax.jcr.RepositoryException; 045import javax.jcr.Session; 046import javax.jcr.ValueFactory; 047import javax.jcr.Workspace; 048import javax.jcr.nodetype.NodeType; 049import javax.jcr.nodetype.NodeTypeIterator; 050import javax.jcr.nodetype.NodeTypeManager; 051import javax.jcr.query.Query; 052import javax.jcr.query.QueryResult; 053import javax.ws.rs.core.MediaType; 054import javax.ws.rs.core.SecurityContext; 055import javax.ws.rs.core.UriBuilder; 056import javax.ws.rs.core.UriInfo; 057 058import org.apache.commons.io.IOUtils; 059import org.apache.http.HttpEntity; 060import org.apache.http.util.EntityUtils; 061import org.apache.jena.riot.Lang; 062 063import org.fcrepo.http.commons.AbstractResource; 064import org.fcrepo.kernel.api.models.NonRdfSourceDescription; 065import org.fcrepo.kernel.api.models.FedoraBinary; 066import org.fcrepo.kernel.api.services.functions.HierarchicalIdentifierSupplier; 067 068import org.mockito.Mockito; 069import org.mockito.invocation.InvocationOnMock; 070import org.mockito.stubbing.Answer; 071import org.modeshape.jcr.api.NamespaceRegistry; 072import org.modeshape.jcr.api.Repository; 073import org.modeshape.jcr.api.query.QueryManager; 074 075import com.hp.hpl.jena.rdf.model.Model; 076import com.hp.hpl.jena.update.GraphStoreFactory; 077 078/** 079 * <p>Abstract TestHelpers class.</p> 080 * 081 * @author awoods 082 */ 083public abstract class TestHelpers { 084 085 public static String MOCK_PREFIX = "mockPrefix"; 086 087 public static String MOCK_URI_STRING = "mock.namespace.org"; 088 089 public static UriInfo getUriInfoImpl() { 090 // UriInfo ui = mock(UriInfo.class,withSettings().verboseLogging()); 091 final UriInfo ui = mock(UriInfo.class); 092 093 final Answer<UriBuilder> answer = new Answer<UriBuilder>() { 094 095 @Override 096 public UriBuilder answer(final InvocationOnMock invocation) { 097 return fromUri("http://localhost/fcrepo"); 098 } 099 }; 100 101 when(ui.getRequestUri()).thenReturn( 102 URI.create("http://localhost/fcrepo")); 103 when(ui.getBaseUri()).thenReturn(create("http://localhost/fcrepo")); 104 when(ui.getBaseUriBuilder()).thenAnswer(answer); 105 when(ui.getAbsolutePathBuilder()).thenAnswer(answer); 106 107 return ui; 108 } 109 110 public static Session getQuerySessionMock() { 111 final Session mock = mock(Session.class); 112 final Workspace mockWS = mock(Workspace.class); 113 final QueryManager mockQM = mock(QueryManager.class); 114 try { 115 final Query mockQ = getQueryMock(); 116 when(mockQM.createQuery(anyString(), anyString())) 117 .thenReturn((org.modeshape.jcr.api.query.Query) mockQ); 118 when(mockWS.getQueryManager()).thenReturn(mockQM); 119 } catch (final RepositoryException e) { 120 e.printStackTrace(); 121 } 122 when(mock.getWorkspace()).thenReturn(mockWS); 123 final ValueFactory mockVF = mock(ValueFactory.class); 124 try { 125 when(mock.getValueFactory()).thenReturn(mockVF); 126 } catch (final RepositoryException e) { 127 e.printStackTrace(); 128 } 129 return mock; 130 } 131 132 @SuppressWarnings("unchecked") 133 public static Query getQueryMock() { 134 final Query mockQ = mock(Query.class); 135 final QueryResult mockResults = mock(QueryResult.class); 136 final NodeIterator mockNodes = mock(NodeIterator.class); 137 when(mockNodes.getSize()).thenReturn(2L); 138 when(mockNodes.hasNext()).thenReturn(true, true, false); 139 final Node node1 = mock(Node.class); 140 final Node node2 = mock(Node.class); 141 try { 142 when(node1.getName()).thenReturn("node1"); 143 when(node2.getName()).thenReturn("node2"); 144 } catch (final RepositoryException e) { 145 e.printStackTrace(); 146 } 147 when(mockNodes.nextNode()).thenReturn(node1, node2).thenThrow( 148 IndexOutOfBoundsException.class); 149 try { 150 when(mockResults.getNodes()).thenReturn(mockNodes); 151 when(mockQ.execute()).thenReturn(mockResults); 152 } catch (final RepositoryException e) { 153 e.printStackTrace(); 154 } 155 return mockQ; 156 } 157 158 @SuppressWarnings("unchecked") 159 public static Session getSessionMock() throws RepositoryException { 160 final String[] mockPrefixes = {MOCK_PREFIX}; 161 final Session mockSession = mock(Session.class); 162 final Workspace mockWorkspace = mock(Workspace.class); 163 final NamespaceRegistry mockNameReg = mock(NamespaceRegistry.class); 164 final NodeTypeManager mockNTM = mock(NodeTypeManager.class); 165 final NodeTypeIterator mockNTI = mock(NodeTypeIterator.class); 166 final NodeType mockNodeType = mock(NodeType.class); 167 when(mockSession.getWorkspace()).thenReturn(mockWorkspace); 168 when(mockWorkspace.getNamespaceRegistry()).thenReturn(mockNameReg); 169 when(mockNameReg.getPrefixes()).thenReturn(mockPrefixes); 170 when(mockNameReg.getURI(MOCK_PREFIX)).thenReturn(MOCK_URI_STRING); 171 when(mockWorkspace.getNodeTypeManager()).thenReturn(mockNTM); 172 when(mockNodeType.getName()).thenReturn("mockName"); 173 when(mockNodeType.toString()).thenReturn("mockString"); 174 when(mockNTM.getAllNodeTypes()).thenReturn(mockNTI); 175 when(mockNTI.hasNext()).thenReturn(true, false); 176 when(mockNTI.nextNodeType()).thenReturn(mockNodeType).thenThrow( 177 ArrayIndexOutOfBoundsException.class); 178 return mockSession; 179 } 180 181 public static Collection<String> 182 parseChildren(final HttpEntity entity) throws IOException { 183 final String body = EntityUtils.toString(entity); 184 System.err.println(body); 185 final String[] names = 186 body.replace("[", "").replace("]", "").trim().split(",\\s?"); 187 return Arrays.asList(names); 188 } 189 190 public static Session mockSession(final AbstractResource testObj) { 191 192 final SecurityContext mockSecurityContext = mock(SecurityContext.class); 193 final Principal mockPrincipal = mock(Principal.class); 194 195 final String mockUser = "testuser"; 196 197 final Session mockSession = mock(Session.class); 198 when(mockSession.getUserID()).thenReturn(mockUser); 199 when(mockSecurityContext.getUserPrincipal()).thenReturn(mockPrincipal); 200 when(mockPrincipal.getName()).thenReturn(mockUser); 201 202 final Workspace mockWorkspace = mock(Workspace.class); 203 when(mockSession.getWorkspace()).thenReturn(mockWorkspace); 204 when(mockWorkspace.getName()).thenReturn("default"); 205 206 setField(testObj, "uriInfo", getUriInfoImpl()); 207 setField(testObj, "pidMinter", new PathMinterImpl()); 208 return mockSession; 209 210 } 211 212 public static Repository mockRepository() throws LoginException, 213 RepositoryException { 214 final Repository mockRepo = mock(Repository.class); 215 when(mockRepo.login()).thenReturn( 216 mock(org.modeshape.jcr.api.Session.class, Mockito.withSettings().extraInterfaces(Session.class))); 217 return mockRepo; 218 } 219 220 public static NonRdfSourceDescription mockDatastream(final String pid, 221 final String dsId, final String content) { 222 final FedoraBinary mockBinary = mockBinary(pid, dsId, content); 223 final NonRdfSourceDescription mockDs = mock(NonRdfSourceDescription.class); 224 when(mockDs.getDescribedResource()).thenReturn(mockBinary); 225 when(mockDs.getDescribedResource().getDescription()).thenReturn(mockDs); 226 when(mockDs.getPath()).thenReturn("/" + pid + "/" + dsId); 227 when(mockDs.getCreatedDate()).thenReturn(new Date()); 228 when(mockDs.getLastModifiedDate()).thenReturn(new Date()); 229 if (content != null) { 230 final MessageDigest md; 231 try { 232 md = MessageDigest.getInstance("SHA-1"); 233 } catch (final NoSuchAlgorithmException e) { 234 throw new RuntimeException(e); 235 } 236 final byte[] digest = md.digest(content.getBytes()); 237 final URI cd = asURI("SHA-1", digest); 238 when(mockDs.getEtagValue()).thenReturn(cd.toString()); 239 } 240 return mockDs; 241 } 242 243 public static FedoraBinary mockBinary(final String pid, 244 final String dsId, final String content) { 245 final FedoraBinary mockBinary = mock(FedoraBinary.class); 246 when(mockBinary.getPath()).thenReturn("/" + pid + "/" + dsId + "/jcr:content"); 247 when(mockBinary.getMimeType()).thenReturn("application/octet-stream"); 248 when(mockBinary.getCreatedDate()).thenReturn(new Date()); 249 when(mockBinary.getLastModifiedDate()).thenReturn(new Date()); 250 if (content != null) { 251 final MessageDigest md; 252 try { 253 md = MessageDigest.getInstance("SHA-1"); 254 } catch (final NoSuchAlgorithmException e) { 255 throw new RuntimeException(e); 256 } 257 final byte[] digest = md.digest(content.getBytes()); 258 final URI cd = asURI("SHA-1", digest); 259 when(mockBinary.getContent()).thenReturn( 260 IOUtils.toInputStream(content)); 261 when(mockBinary.getContentDigest()).thenReturn(cd); 262 when(mockBinary.getEtagValue()).thenReturn(cd.toString()); 263 } 264 return mockBinary; 265 } 266 267 private static String getRdfSerialization(final HttpEntity entity) { 268 final MediaType mediaType = MediaType.valueOf(entity.getContentType().getValue()); 269 final Lang lang = contentTypeToLang(mediaType.toString()); 270 assertNotNull("Entity is not an RDF serialization", lang); 271 return lang.getName(); 272 } 273 274 public static CloseableGraphStore parseTriples(final HttpEntity entity) throws IOException { 275 return parseTriples(entity.getContent(), getRdfSerialization(entity)); 276 } 277 278 public static CloseableGraphStore parseTriples(final InputStream content) { 279 return parseTriples(content, "N3"); 280 } 281 282 public static CloseableGraphStore parseTriples(final InputStream content, final String contentType) { 283 final Model model = createDefaultModel(); 284 model.read(content, "", contentType); 285 return new CloseableGraphStore(GraphStoreFactory.create(model)); 286 } 287 288 /** 289 * Set a field via reflection 290 * 291 * @param parent the owner object of the field 292 * @param name the name of the field 293 * @param obj the value to set 294 */ 295 public static void setField(final Object parent, final String name, final Object obj) { 296 /* check the parent class too if the field could not be found */ 297 try { 298 final Field f = findField(parent.getClass(), name); 299 f.setAccessible(true); 300 f.set(parent, obj); 301 } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) { 302 throw new RuntimeException(e); 303 } 304 } 305 306 private static Field findField(final Class<?> clazz, final String name) 307 throws NoSuchFieldException { 308 for (final Field f : clazz.getDeclaredFields()) { 309 if (f.getName().equals(name)) { 310 return f; 311 } 312 } 313 if (clazz.getSuperclass() == null) { 314 throw new NoSuchFieldException("Field " + name 315 + " could not be found"); 316 } 317 return findField(clazz.getSuperclass(), name); 318 } 319 320 private static class PathMinterImpl implements HierarchicalIdentifierSupplier { } 321}