Permalink
Browse files

MODE-1286 Initial Git connector implementation

Added a connector implementation that accesses a Git repository. The connector was written to validate the Connector SPI, and was useful in improving the SPI (e.g., paging functionality). However, the connector has not been tested and is nearly complete, and so the connector is not yet incorporated into the build.
  • Loading branch information...
1 parent 11bec36 commit 4ecbecb648babd16cf610dd07ab4b1093f7310a2 @rhauch rhauch committed Nov 20, 2012
Showing with 2,518 additions and 371 deletions.
  1. +38 −0 connectors/modeshape-connector-git/pom.xml
  2. +105 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/CallSpecification.java
  3. +130 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitBinaryValue.java
  4. +91 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitBranches.java
  5. +161 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitCommitDetails.java
  6. +149 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitConnector.java
  7. +98 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitFunction.java
  8. +166 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitHistory.java
  9. +67 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitLexicon.java
  10. +60 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitRoot.java
  11. +91 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitTags.java
  12. +255 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitTree.java
  13. +45 −0 ...ectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/PageableGitFunction.java
  14. +72 −0 connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/Values.java
  15. +113 −0 connectors/modeshape-connector-git/src/main/resources/org/modeshape/connector/git/git.cnd
  16. +299 −0 connectors/modeshape-connector-git/src/test/java/org/modeshape/connector/git/GitFunctionalTest.java
  17. +98 −0 connectors/pom.xml
  18. +3 −96 modeshape-jcr/src/main/java/org/modeshape/connector/filesystem/FileSystemConnector.java
  19. +12 −4 modeshape-jcr/src/main/java/org/modeshape/jcr/cache/document/DocumentTranslator.java
  20. +2 −4 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/FederatedDocumentReader.java
  21. +15 −5 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/FederatedDocumentStore.java
  22. +24 −10 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/FederatedDocumentWriter.java
  23. +27 −2 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Connector.java
  24. +26 −26 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/DocumentReader.java
  25. +119 −131 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/DocumentWriter.java
  26. +1 −1 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/ExtraPropertiesStore.java
  27. +105 −0 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/PageWriter.java
  28. +10 −10 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Pageable.java
  29. +0 −66 modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/PagingWriter.java
  30. +103 −0 modeshape-jcr/src/main/java/org/modeshape/jcr/value/binary/UrlBinaryValue.java
  31. +24 −16 modeshape-jcr/src/test/java/org/modeshape/connector/testing/mock/MockConnector.java
  32. +9 −0 modeshape-parent/pom.xml
@@ -0,0 +1,38 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.modeshape</groupId>
+ <artifactId>modeshape-connectors</artifactId>
+ <version>3.1-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <!-- The groupId and version values are inherited from parent -->
+ <artifactId>modeshape-connector-git</artifactId>
+ <packaging>jar</packaging>
+ <name>ModeShape Connector to Git Repositories</name>
+ <description>ModeShape Connector that access the content in a Git repository</description>
+ <url>http://www.modeshape.org</url>
+
+ <!--
+ Define the dependencies. Note that all version and scopes default to those
+ defined in the dependencyManagement section of the parent pom.
+ -->
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>${project.basedir}/src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>${project.basedir}/src/test/java</directory>
+ </testResource>
+ </testResources>
+ </build>
+</project>
@@ -0,0 +1,105 @@
+/*
+ * ModeShape (http://www.modeshape.org)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * ModeShape is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.modeshape.connector.git;
+
+import org.modeshape.common.annotation.Immutable;
+
+/**
+ *
+ */
+@Immutable
+public final class CallSpecification {
+
+ protected static final String DELIMITER_STR = "/";
+ protected static final char DELIMITER = DELIMITER_STR.charAt(0);
+
+ private final String id;
+ private final String[] parts;
+ private final int numParts;
+ private final int parameterCount;
+
+ public CallSpecification( String id ) {
+ this.id = id;
+ this.parts = id.split("[/]");
+ assert this.parts.length > 0;
+ this.numParts = this.parts.length;
+ this.parameterCount = numParts - 1;
+ }
+
+ public String getFunctionName() {
+ return this.parts[0];
+ }
+
+ public int parameterCount() {
+ return parameterCount;
+ }
+
+ public String parameter( int index ) {
+ return parts[index + 1];
+ }
+
+ public String parametersAsPath( int fromIndex ) {
+ return parametersAsPath(fromIndex, numParts);
+ }
+
+ public String parametersAsPath( int fromIndex,
+ int toIndex ) {
+ assert fromIndex < numParts;
+ assert toIndex <= numParts;
+ StringBuilder sb = new StringBuilder();
+ for (int i = fromIndex; i != toIndex; ++i) {
+ sb.append(DELIMITER);
+ sb.append(parts[i]);
+ }
+ return sb.toString();
+ }
+
+ public String lastParameter() {
+ if (numParts == 0) return null;
+ return this.parts[numParts - 1];
+ }
+
+ public String childId( String childPart ) {
+ return id + DELIMITER + childPart;
+ }
+
+ public String getParentId() {
+ if (numParts == 0) {
+ // There is no parent ...
+ return "";
+ }
+ if (numParts == 1) {
+ // The parent is the root ...
+ return GitRoot.ID;
+ }
+ StringBuilder sb = new StringBuilder();
+ int length = numParts - 1;
+ for (int i = 0; i != length; ++i) {
+ String part = parts[i];
+ sb.append(DELIMITER);
+ sb.append(part);
+ }
+ return sb.toString();
+ }
+}
@@ -0,0 +1,130 @@
+/*
+ * ModeShape (http://www.modeshape.org)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * ModeShape is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.modeshape.connector.git;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import javax.jcr.RepositoryException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.modeshape.common.logging.Logger;
+import org.modeshape.jcr.mimetype.MimeTypeDetector;
+import org.modeshape.jcr.value.BinaryKey;
+import org.modeshape.jcr.value.BinaryValue;
+import org.modeshape.jcr.value.binary.AbstractBinary;
+
+/**
+ * A {@link BinaryValue} implementation used to read the content of a specific object ID from the supplied repository. This class
+ * computes the {@link AbstractBinary#getMimeType() MIME type} lazily or upon serialization.
+ */
+public class GitBinaryValue extends AbstractBinary implements Externalizable {
+ private static final long serialVersionUID = 1L;
+
+ private transient MimeTypeDetector mimeTypeDetector;
+ private transient String nameHint; // only needed for MIME type detection; not needed once MIME type is known
+ private transient ObjectLoader loader;
+ private transient ObjectId id;
+ private String mimeType;
+ private long size = -1L;
+ private boolean detectedMimeType = false;
+ private byte[] serializedBytes;
+
+ public GitBinaryValue( ObjectId id,
+ ObjectLoader loader,
+ String nameHint,
+ MimeTypeDetector mimeTypeDetector ) {
+ super(new BinaryKey(id.getName()));
+ this.id = id;
+ this.loader = loader;
+ this.size = loader.getSize();
+ this.nameHint = nameHint;
+ this.mimeTypeDetector = mimeTypeDetector;
+ }
+
+ protected boolean hasMimeType() {
+ return mimeType != null;
+ }
+
+ @Override
+ public String getMimeType() {
+ if (!detectedMimeType && mimeTypeDetector != null) {
+ try {
+ mimeType = mimeTypeDetector.mimeTypeOf(nameHint, this);
+ } catch (Throwable t) {
+ Logger.getLogger(getClass()).debug("Unable to compute MIME Type for file {0}", id);
+ throw new RuntimeException(t);
+ } finally {
+ detectedMimeType = true;
+ }
+ }
+ return mimeType;
+ }
+
+ @Override
+ public String getMimeType( String name ) {
+ return getMimeType();
+ }
+
+ @Override
+ public long getSize() {
+ return size;
+ }
+
+ @Override
+ public InputStream getStream() throws RepositoryException {
+ try {
+ if (serializedBytes != null) {
+ return new ByteArrayInputStream(serializedBytes);
+ }
+ return new BufferedInputStream(loader.openStream());
+ } catch (IOException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ @Override
+ public void readExternal( ObjectInput in ) throws IOException {
+ this.mimeType = in.readUTF();
+ this.detectedMimeType = in.readBoolean();
+ this.size = in.readLong();
+ int numBytes = in.readInt();
+ this.serializedBytes = new byte[numBytes];
+ in.read(this.serializedBytes);
+ }
+
+ @Override
+ public void writeExternal( ObjectOutput out ) throws IOException {
+ out.writeUTF(getMimeType());
+ out.writeBoolean(detectedMimeType);
+ out.writeLong(getSize());
+ byte[] bytes = loader.getCachedBytes();
+ out.writeInt(bytes.length);
+ out.write(bytes);
+ }
+}
@@ -0,0 +1,91 @@
+/*
+ * ModeShape (http://www.modeshape.org)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * ModeShape is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.modeshape.connector.git;
+
+import java.io.IOException;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.infinispan.schematic.document.Document;
+import org.modeshape.jcr.federation.spi.DocumentWriter;
+
+/**
+ * A {@link GitFunction} that returns the list of branches in this repository. The structure of this area of the repository is as
+ * follows:
+ *
+ * <pre>
+ * /branches/{branchName}
+ * </pre>
+ */
+public class GitBranches extends GitFunction {
+
+ protected static final String NAME = "branches";
+ protected static final String ID = "/branches";
+
+ public GitBranches( GitConnector connector ) {
+ super(NAME, connector);
+ }
+
+ @Override
+ public Document execute( Repository repository,
+ Git git,
+ CallSpecification spec,
+ DocumentWriter writer,
+ Values values ) throws GitAPIException, IOException {
+ if (spec.parameterCount() == 0) {
+ // This is the top-level "/branches" node
+ writer.setPrimaryType(GitLexicon.BRANCHES);
+
+ // Generate the child references to the branches ...
+ addBranchesAsChildren(git, spec, writer);
+
+ } else if (spec.parameterCount() == 1) {
+ // This is a particular branch node ...
+ writer.setPrimaryType(GitLexicon.BRANCH);
+ String branchName = spec.parameter(1);
+ // Get the Ref, which doesn't directly know about the commit SHA1, so we have to parse the commit ...
+ Ref ref = repository.getRef(branchName);
+ if (ref == null) return null; // invalid branch
+ RevWalk walker = new RevWalk(repository);
+ try {
+ RevCommit commit = walker.parseCommit(ref.getObjectId());
+ // Construct the references to other nodes in this source ...
+ ObjectId objId = commit.getId();
+ writer.addProperty(GitLexicon.OBJECT_ID, objId.name());
+ writer.addProperty(GitLexicon.TREE, GitTree.referenceToTree(objId, values));
+ writer.addProperty(GitLexicon.HISTORY, GitHistory.referenceToHistory(objId, branchName, values));
+ } finally {
+ walker.dispose();
+ }
+ } else {
+ return null;
+ }
+
+ return writer.document();
+ }
+}
Oops, something went wrong.

0 comments on commit 4ecbecb

Please sign in to comment.