Skip to content

Commit

Permalink
added projection mixin type and a FileSystemConnector which is able t…
Browse files Browse the repository at this point in the history
…o inject this mixin type
  • Loading branch information
fasseg committed Dec 6, 2013
1 parent d4e8b10 commit ef8d383
Show file tree
Hide file tree
Showing 2 changed files with 260 additions and 0 deletions.
2 changes: 2 additions & 0 deletions fcrepo-jcr/src/main/java/org/fcrepo/jcr/FedoraJcrTypes.java
Expand Up @@ -50,4 +50,6 @@ public interface FedoraJcrTypes {
String FROZEN_NODE = "nt:frozenNode";

String FROZEN_MIXIN_TYPES = "jcr:frozenMixinTypes";

String FEDORA_PROJECTION ="fedora:projection";
}
@@ -0,0 +1,258 @@
/**
* Copyright 2013 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.modeshape.jcr;

import java.io.File;
import java.util.regex.Pattern;

import org.fcrepo.jcr.FedoraJcrTypes;
import org.infinispan.schematic.document.Document;
import org.modeshape.connector.filesystem.FileSystemConnector;
import org.modeshape.jcr.federation.spi.DocumentWriter;
import org.modeshape.jcr.value.BinaryValue;

/**
* This {@link FileSystemConnector} implementation injects a mixin type "fedora:projection" when a node is read
* form a projected file system
*
* @author fasseg
*
*/
public class FedoraFileSystemConnector extends FileSystemConnector {

/* Unfortunately a lot of the stuff in FileSystemConnector is private
* and had to be copied
*/
private static final String FILE_SEPARATOR = System
.getProperty("file.separator");

private static final String DELIMITER = "/";

private static final String NT_FOLDER = "nt:folder";

private static final String NT_FILE = "nt:file";

private static final String NT_RESOURCE = "nt:resource";

private static final String JCR_DATA = "jcr:data";

private static final String JCR_MIME_TYPE = "jcr:mimeType";

private static final String JCR_ENCODING = "jcr:encoding";

private static final String JCR_CREATED = "jcr:created";

private static final String JCR_CREATED_BY = "jcr:createdBy";

private static final String JCR_LAST_MODIFIED = "jcr:lastModified";

private static final String JCR_LAST_MODIFIED_BY = "jcr:lastModified";

private static final String JCR_CONTENT = "jcr:content";

private static final String JCR_CONTENT_SUFFIX = DELIMITER + JCR_CONTENT;

private static final String MIX_MIME_TYPE = "mix:mimeType";

private final boolean addMimeTypeMixin = false;

private final int pageSize = 20;

private InclusionExclusionFilenameFilter filenameFilter;

@Override
public Document getDocumentById(String id) {
File file = fileFor(id);
if (isExcluded(file) || !file.exists()) {
return null;
}
boolean isRoot = isRoot(id);
boolean isResource = isContentNode(id);
DocumentWriter writer = null;
File parentFile = file.getParentFile();
if (isResource) {
writer = newDocument(id);
BinaryValue binaryValue = binaryFor(file);
writer.setPrimaryType(NT_RESOURCE);
writer.addProperty(JCR_DATA, binaryValue);
if (addMimeTypeMixin) {
String mimeType = null;
String encoding = null; // We don't really know this
try {
mimeType = binaryValue.getMimeType();
} catch (Throwable e) {
getLogger().error(e, JcrI18n.couldNotGetMimeType,
getSourceName(), id, e.getMessage());
}
writer.addProperty(JCR_ENCODING, encoding);
writer.addProperty(JCR_MIME_TYPE, mimeType);
}
writer.addProperty(JCR_LAST_MODIFIED, factories().getDateFactory()
.create(file.lastModified()));
writer.addProperty(JCR_LAST_MODIFIED_BY, null); // ignored

// make these binary not queryable. If we really want to query them, we need to switch to external binaries
writer.setNotQueryable();
parentFile = file;
} else if (file.isFile()) {
writer = newDocument(id);
writer.setPrimaryType(NT_FILE);
writer.addProperty(JCR_CREATED, factories().getDateFactory()
.create(file.lastModified()));
writer.addProperty(JCR_CREATED_BY, null); // ignored
String childId =
isRoot ? JCR_CONTENT_SUFFIX : id + JCR_CONTENT_SUFFIX;
writer.addChild(childId, JCR_CONTENT);
} else {
writer = this.newFolderWriter(id, file, 0);
}

if (!isRoot) {
// Set the reference to the parent ...
String parentId = idFor(parentFile);
writer.setParents(parentId);
}

// Add the extra properties (if there are any), overwriting any properties with the same names
// (e.g., jcr:primaryType, jcr:mixinTypes, jcr:mimeType, etc.) ...
writer.addProperties(extraPropertiesStore().getProperties(id));

// Add the 'mix:mixinType' mixin; if other mixins are stored in the extra properties, this will append ...
if (addMimeTypeMixin) {
writer.addMixinType(MIX_MIME_TYPE);
}

// Add the "fedora:projection" mixin types so a node can be recognized as a projection
writer.addMixinType(FedoraJcrTypes.FEDORA_PROJECTION);

// Return the document ...
return writer.document();
}

private DocumentWriter newFolderWriter(String id, File file, int offset) {
boolean root = isRoot(id);
DocumentWriter writer = newDocument(id);
writer.setPrimaryType(NT_FOLDER);
writer.addProperty(JCR_CREATED, factories().getDateFactory().create(
file.lastModified()));
writer.addProperty(JCR_CREATED_BY, null); // ignored
File[] children = file.listFiles(filenameFilter);
long totalChildren = 0;
int nextOffset = 0;
for (int i = 0; i < children.length; i++) {
File child = children[i];
// Only include as a child if we can access and read the file. Permissions might prevent us from
// reading the file, and the file might not exist if it is a broken symlink (see MODE-1768 for details).
if (child.exists() && child.canRead() &&
(child.isFile() || child.isDirectory())) {
// we need to count the total accessible children
totalChildren++;
// only add a child if it's in the current page
if (i >= offset && i < offset + pageSize) {
// We use identifiers that contain the file/directory name ...
String childName = child.getName();
String childId =
root ? DELIMITER + childName : id + DELIMITER +
childName;
writer.addChild(childId, childName);
nextOffset = i + 1;
}
}
}
// if there are still accessible children add the next page
if (nextOffset < totalChildren) {
writer.addPage(id, nextOffset, pageSize, totalChildren);
}
return writer;
}

class InclusionExclusionFilenameFilter implements java.io.FilenameFilter {

private String inclusionPattern = null;

private String exclusionPattern = null;

private Pattern inclusion;

private Pattern exclusion;

private Pattern extraPropertiesExclusion;

public void setExclusionPattern(String exclusionPattern) {
this.exclusionPattern = exclusionPattern;
if (exclusionPattern == null) {
this.exclusion = null;
} else {
this.exclusion = Pattern.compile(exclusionPattern);
}
}

public void setExtraPropertiesExclusionPattern(String exclusionPattern) {
if (exclusionPattern == null) {
this.extraPropertiesExclusion = null;
} else {
this.extraPropertiesExclusion =
Pattern.compile(exclusionPattern);
}
}

public void setInclusionPattern(String inclusionPattern) {
this.inclusionPattern = inclusionPattern;
if (inclusionPattern == null) {
this.inclusion = null;
} else {
this.inclusion = Pattern.compile(inclusionPattern);
}
}

public String getExclusionPattern() {
return exclusionPattern;
}

public String getInclusionPattern() {
return inclusionPattern;
}

@Override
public boolean accept(File file, String name) {
if (inclusionPattern == null) {
// Include unless it matches an exclusion ...
if (exclusionPattern != null &&
exclusion.matcher(name).matches()) {
return false;
}
if (extraPropertiesExclusion != null &&
extraPropertiesExclusion.matcher(name).matches()) {
return false;
}
return true;
}
// Include ONLY if it matches the inclusion AND not matched by the exclusions ...
if (!inclusion.matcher(name).matches()) {
return false;
}
if (exclusionPattern != null && exclusion.matcher(name).matches()) {
return false;
}
if (extraPropertiesExclusion != null &&
extraPropertiesExclusion.matcher(name).matches()) {
return false;
}
return true;
}
}

}

0 comments on commit ef8d383

Please sign in to comment.