Skip to content
This repository has been archived by the owner on Jan 3, 2019. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Implementation for no binary content jcr/xml file system persistence.
  • Loading branch information
lsitu authored and Andrew Woods committed Jul 24, 2014
1 parent 886bbea commit b78416a
Show file tree
Hide file tree
Showing 7 changed files with 434 additions and 2 deletions.
Expand Up @@ -64,7 +64,7 @@ public interface Indexer<Content> {
* @date Dec 14, 2013
*/
public static enum IndexerType {
NAMEDFIELDS, RDF, NO_CONTENT
NAMEDFIELDS, RDF, NO_CONTENT, JCRXML_PERSISTENCE
}

/**
Expand Down
Expand Up @@ -20,6 +20,7 @@
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
Expand All @@ -34,6 +35,8 @@
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;

import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.util.HashSet;
Expand Down Expand Up @@ -230,6 +233,8 @@ private void index( final String uri, final String eventType ) {
memoize(new RdfRetriever(uri, httpClient));
final Supplier<NamedFields> nfr =
memoize(new NamedFieldsRetriever(uri, httpClient, rdfr));
final Supplier<InputStream> jcrfr =
memoize(new JcrXmlRetriever(uri, httpClient));
Boolean indexable = false;

if (!removal) {
Expand Down Expand Up @@ -278,6 +283,13 @@ private void index( final String uri, final String eventType ) {
content = rdfr.get();
hasContent = true;
break;
case JCRXML_PERSISTENCE:
LOGGER.debug(
"Retrieving jcr/xml for: {} and persist it to {}...",
uri, indexer);
content = jcrfr.get();
hasContent = true;
break;
default:
hasContent = true;
break;
Expand All @@ -304,7 +316,7 @@ private void index( final String uri, final String eventType ) {
}
}
} catch (final Exception e) {
LOGGER.error("Error indexing {}: {}!", uri, e);
LOGGER.error("Error {} indexing {}: {}!", indexer.getClass().getName(), uri, e);
}
}
}
Expand Down
@@ -0,0 +1,75 @@
/**
* Copyright 2014 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fcrepo.indexer;

import static com.google.common.base.Throwables.propagate;
import static org.apache.http.HttpStatus.SC_OK;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.slf4j.Logger;

import com.google.common.base.Supplier;

/**
* Retrieves Modeshape jcr/xml for file system persistence
* @author lsitu
*/
public class JcrXmlRetriever implements Supplier<InputStream> {

private final String identifier;

private final HttpClient httpClient;

private static final Logger LOGGER = getLogger(JcrXmlRetriever.class);

/**
* Constructor
* @param identifier
* @param client
*/
public JcrXmlRetriever(final String identifier, final HttpClient client) {
this.identifier = identifier;
this.httpClient = client;
}

@Override
/**
* Retrieve jcr/xml with no binary contents from the repository
*/
public InputStream get() {
final HttpUriRequest request = new HttpGet(identifier + "/fcr:export?skipBinary=true");
LOGGER.debug("Retrieving jcr/xml content from: {}...", request.getURI());
try {
final HttpResponse response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() == SC_OK) {
return response.getEntity().getContent();
} else {
throw new HttpException(response.getStatusLine().toString());
}
} catch (IOException | HttpException e) {
throw propagate(e);
}
}

}
@@ -0,0 +1,107 @@
/**
* Copyright 2014 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fcrepo.indexer.persistence;

import static org.fcrepo.indexer.Indexer.IndexerType.JCRXML_PERSISTENCE;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.Callable;

import org.fcrepo.indexer.SynchIndexer;
import org.slf4j.Logger;

/**
* Basic Indexer implementation to write contents from an InputStream files on disk.
* @author ajs6f
* @author Esmé Cowles
* @date Aug 19, 2013
* @author lsitu
**/
public class JcrXmlPersistenceIndexer extends SynchIndexer<InputStream, File> {

private static final Logger LOGGER = getLogger(JcrXmlPersistenceIndexer.class);

private File path = null;

/**
* Constructor
* @param pathName of directory in which jcr/xml exports will be stored
*/
public JcrXmlPersistenceIndexer(final String pathName) {
this.path = new File(pathName);
if (!this.path.exists()) {
this.path.mkdirs();
}
}

/**
* Create/update an index entry for the object.
* @param id
* @param content
* @return
**/
@Override
public Callable<File> updateSynch(final String id, final InputStream content) {

if (id.endsWith("/")) {
throw new IllegalArgumentException(
"Identifiers for use with this indexer may not end in '/'!");
}

return new Callable<File>() {

@Override
public File call() throws IOException {
// file name with object identifier
final String fileName = URLEncoder.encode(id, "UTF-8") + "-jcr.xml";

LOGGER.debug("Updating {} to file: {}", id, getPath() + File.pathSeparatorChar + fileName);
// write content to disk
final Path p = Paths.get(getPath(), fileName);
Files.copy(content, p, new CopyOption[]{});
return p.toFile();
}
};
}

private String getPath() {
return path.getAbsolutePath();
}

/**
* Remove the object from the file system.
**/
@Override
public Callable<File> removeSynch(final String id) {
// empty update
LOGGER.debug("Received remove for identifier: {}", id);
return updateSynch(id, new ByteArrayInputStream("".getBytes()));
}

@Override
public IndexerType getIndexerType() {
return JCRXML_PERSISTENCE;
}
}
@@ -0,0 +1,123 @@
/**
* Copyright 2014 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fcrepo.indexer;

import static org.apache.http.HttpStatus.SC_FORBIDDEN;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_OK;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

/**
* Test retrieve jcr/xml from the repository
* @author ajs6
* @author lsitu
*/
public class JcrXmlRetrieverTest {

private JcrXmlRetriever testRetriever;

@Mock
private HttpClient mockClient;

@Mock
private HttpResponse mockResponse;

@Mock
private HttpEntity mockEntity;

@Mock
private StatusLine mockStatusLine;

private final String testContent =
"<sv:node xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" sv:name=\"testContent\"></sv:node>";

@Before
public void setUp() throws IOException {
initMocks(this);
when(mockClient.execute(any(HttpUriRequest.class))).thenReturn(mockResponse);
when(mockResponse.getEntity()).thenReturn(mockEntity);
when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
}

@Test
public void testSimpleRetrieval() throws IOException {
final String testId = "testSimpleRetrieval";
final InputStream input = new ByteArrayInputStream (testContent.getBytes());
when(mockStatusLine.getStatusCode()).thenReturn(SC_OK);
when(mockEntity.getContent()).thenReturn(input);

testRetriever = new JcrXmlRetriever(testId, mockClient);
final InputStream result = testRetriever.get();
final ByteArrayOutputStream out = new ByteArrayOutputStream();
int ch;
while ((ch = result.read()) != -1) {
out.write(ch);
}
out.close();
result.close();
assertTrue("Didn't find our test triple!", out.toString().equals(testContent));
}

@Test(expected = RuntimeException.class)
public void testFailedRetrieval() {
final String testId = "testFailedRetrieval";
when(mockStatusLine.getStatusCode()).thenReturn(SC_NOT_FOUND);
new JcrXmlRetriever(testId, mockClient).get();
}

@Test(expected = RuntimeException.class)
public void testOtherFailedRetrieval() throws IOException {
final String testId = "testFailedRetrieval";
when(mockStatusLine.getStatusCode()).thenReturn(SC_OK);
when(mockEntity.getContent()).thenThrow(new IOException());
new JcrXmlRetriever(testId, mockClient).get();
}

@Test(expected = RuntimeException.class)
public void testYetOtherFailedRetrieval() throws IOException {
final String testId = "testFailedRetrieval";
reset(mockClient);
when(mockClient.execute(any(HttpUriRequest.class))).thenThrow(new IOException());
when(mockStatusLine.getStatusCode()).thenReturn(SC_OK);
when(mockEntity.getContent()).thenThrow(new IOException());
new JcrXmlRetriever(testId, mockClient).get();
}

@Test(expected = RuntimeException.class)
public void testAuthForbiddenRetrieval() {
final String testId = "testAuthForbiddenRetrieval";
when(mockStatusLine.getStatusCode()).thenReturn(SC_FORBIDDEN);
new JcrXmlRetriever(testId, mockClient).get();
}
}

0 comments on commit b78416a

Please sign in to comment.