View Javadoc
1   package net.trajano.wagon.git.internal;
2   
3   import static java.lang.String.format;
4   
5   import java.io.UnsupportedEncodingException;
6   import java.net.URI;
7   import java.net.URLDecoder;
8   
9   import org.apache.commons.lang3.builder.EqualsBuilder;
10  import org.apache.commons.lang3.builder.HashCodeBuilder;
11  import org.apache.commons.lang3.builder.ToStringBuilder;
12  
13  /**
14   * Git URI. This provides the logic to extract the components from a URI. The
15   * URI string is in the form
16   * <code>git:gitSpecificUri?branchName#relativeDirectory</code>.
17   */
18  public class GitUri {
19      /**
20       * Branch name.
21       */
22      private final String branchName;
23  
24      /**
25       * Repository URI.
26       */
27      private final String gitRepositoryUri;
28  
29      /**
30       * Resource. This is the fragment part of the URI.
31       */
32      private final String resource;
33  
34      /**
35       * Constructs the URI based on the parts.
36       *
37       * @param gitRepositoryUri
38       *            git repository URL.
39       * @param branchName
40       *            branch name usually "gh-pages"
41       * @param resource
42       *            resource
43       */
44      public GitUri(final String gitRepositoryUri, final String branchName,
45              final String resource) {
46          this.gitRepositoryUri = gitRepositoryUri;
47          this.branchName = branchName;
48          this.resource = resource;
49      }
50  
51      /**
52       *
53       * @param gitUri
54       *            valid git URI (i.e. no git: schema).
55       */
56      private GitUri(final URI gitUri) {
57          branchName = gitUri.getQuery();
58          final String asciiUriString = gitUri.toASCIIString();
59          gitRepositoryUri = asciiUriString.substring(0,
60                  asciiUriString.lastIndexOf('?'));
61          resource = gitUri.getFragment();
62      }
63  
64      @Override
65      public boolean equals(final Object obj) {
66          if (obj == null) {
67              return false;
68          }
69          if (obj == this) {
70              return true;
71          }
72          if (obj.getClass() != getClass()) {
73              return false;
74          }
75          final GitUri x = (GitUri) obj;
76          return new EqualsBuilder().append(branchName, x.branchName)
77                  .append(gitRepositoryUri, x.gitRepositoryUri)
78                  .append(resource, x.resource).build();
79      }
80  
81      /**
82       * Branch name.
83       *
84       * @return branch name
85       */
86      public String getBranchName() {
87          return branchName;
88      }
89  
90      /**
91       * Git repository URI. This returns a string as that is what is being used
92       * by the JGit API.
93       *
94       * @return Git repository URI
95       */
96      public String getGitRepositoryUri() {
97          return gitRepositoryUri;
98      }
99  
100     public String getResource() {
101         return resource;
102     }
103 
104     @Override
105     public int hashCode() {
106         return new HashCodeBuilder().append(resource).append(branchName)
107                 .append(gitRepositoryUri).build();
108     }
109 
110     /**
111      * Resolves a new {@link GitUri} with the fragment. The schema portion will
112      * find the last occurrence of a URI path segment with a "?" character as
113      * the Git URI with the branch name.
114      *
115      * @param fragment
116      *            may contain escaped characters.
117      * @return resolved {@link GitUri}
118      */
119     public GitUri resolve(final String fragment) {
120         // TODO clean this up so it is less "hacky"
121         final String decodedFragment;
122         try {
123             decodedFragment = URLDecoder.decode(fragment, "UTF-8");
124         } catch (final UnsupportedEncodingException e) {
125             // should not happen.
126             throw new IllegalStateException(e);
127         }
128         final URI combined;
129         if (resource != null) {
130             combined = URI.create(gitRepositoryUri
131                     + resource.replace("##", "#"));
132         } else {
133             combined = URI.create(gitRepositoryUri);
134         }
135         final String slashAppendedUri = combined.toASCIIString();
136         final URI resolvedUri = URI.create(slashAppendedUri).resolve(
137                 decodedFragment.replace(" ", "%2520"));
138         final StringBuilder resolved = new StringBuilder(
139                 resolvedUri.toASCIIString());
140 
141         final int lastQuestionMark = resolved.lastIndexOf("?");
142         if (lastQuestionMark == -1) {
143             return new GitUri(URI.create(format("%s?%s#%s", gitRepositoryUri,
144                     branchName, decodedFragment.replace(" ", "%20"))));
145         }
146         final int lastRelevantSlash = resolved.indexOf("/", lastQuestionMark);
147         final int lastRelevantHash = resolved.indexOf("#", lastQuestionMark);
148 
149         if (lastRelevantSlash > 0 && lastRelevantHash >= lastRelevantSlash) {
150             resolved.insert(lastRelevantSlash, '#');
151         }
152 
153         return new GitUri(URI.create(resolved.toString()));
154     }
155 
156     @Override
157     public String toString() {
158         return new ToStringBuilder(this).append(gitRepositoryUri)
159                 .append(branchName).append(resource).build();
160     }
161 }