View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.scm.provider.svn.repository;
20  
21  import org.apache.maven.scm.provider.ScmProviderRepository;
22  import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
23  import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
24  
25  /**
26   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
27   *
28   */
29  public class SvnScmProviderRepository extends ScmProviderRepositoryWithHost {
30      /** */
31      private String url;
32  
33      private String protocol;
34  
35      /**
36       * The base directory for any tags. Can be relative to the repository URL or an absolute URL.
37       */
38      private String tagBase;
39  
40      /**
41       * The base directory for any branches. Can be relative to the repository URL or an absolute URL.
42       */
43      private String branchBase;
44  
45      public SvnScmProviderRepository(String url) {
46          parseUrl(url);
47  
48          tagBase = SvnTagBranchUtils.resolveTagBase(url);
49  
50          branchBase = SvnTagBranchUtils.resolveBranchBase(url);
51      }
52  
53      public SvnScmProviderRepository(String url, String user, String password) {
54          this(url);
55  
56          setUser(user);
57  
58          setPassword(password);
59      }
60  
61      public String getUrl() {
62          return url;
63      }
64  
65      /**
66       * Returns the url/directory to be used when tagging this repository.
67       */
68      public String getTagBase() {
69          return tagBase;
70      }
71  
72      /**
73       * Sets the url/directory to be used when tagging this repository.
74       * The TagBase is a way to override the default tag location for the
75       * repository.  The default tag location is automatically determined
76       * for repositories in the standard subversion layout (with /tags /branches /trunk).
77       * Specify this value only if the repository is using a directory other than "/tags" for tagging.
78       *
79       * @param tagBase an absolute or relative url to the base directory to create tags in.
80       *                URL should be in a format that svn client understands, not the scm url format.
81       */
82      public void setTagBase(String tagBase) {
83          this.tagBase = tagBase;
84      }
85  
86      /**
87       * Returns the url/directory to be used when tagging this repository.
88       */
89      public String getBranchBase() {
90          return branchBase;
91      }
92  
93      /**
94       * Sets the url/directory to be used when branching this repository.
95       * The BranchBase is a way to override the default branch location for the
96       * repository.  The default branch location is automatically determined
97       * for repositories in the standard subversion layout (with /tags /branches /trunk).
98       * Specify this value only if the repository is using a directory other than "/branches" for branching.
99       *
100      * @param branchBase an absolute or relative url to the base directory to create branch in.
101      *                   URL should be in a format that svn client understands, not the scm url format.
102      */
103     public void setBranchBase(String branchBase) {
104         this.branchBase = branchBase;
105     }
106 
107     private void setProtocol(String protocol) {
108         this.protocol = protocol;
109     }
110 
111     /**
112      * Get the protocol used in this repository (file://, http://, https://,...)
113      *
114      * @return the protocol
115      */
116     public String getProtocol() {
117         return protocol;
118     }
119 
120     private void parseUrl(String url) {
121         if (url.startsWith("file")) {
122             setProtocol("file://");
123         } else if (url.startsWith("https")) {
124             setProtocol("https://");
125         } else if (url.startsWith("http")) {
126             setProtocol("http://");
127         } else if (url.startsWith("svn+")) {
128             setProtocol(url.substring(0, url.indexOf("://") + 3));
129         } else if (url.startsWith("svn")) {
130             setProtocol("svn://");
131         }
132 
133         if (getProtocol() == null) {
134             return;
135         }
136 
137         String urlPath = url.substring(getProtocol().length());
138 
139         int indexAt = urlPath.indexOf('@');
140 
141         // a file:// URL may contain userinfo according to RFC 8089, but our implementation is broken
142         // extract user information, broken see SCM-909
143         if (indexAt > 0 && !getProtocol().startsWith("svn+") && !getProtocol().equals("file://")) {
144             String userPassword = urlPath.substring(0, indexAt);
145             if (userPassword.indexOf(':') < 0) {
146                 setUser(userPassword);
147             } else {
148                 setUser(userPassword.substring(0, userPassword.indexOf(':')));
149                 setPassword(userPassword.substring(userPassword.indexOf(':') + 1));
150             }
151 
152             urlPath = urlPath.substring(indexAt + 1);
153 
154             this.url = getProtocol() + urlPath;
155         } else {
156             this.url = getProtocol() + urlPath;
157         }
158 
159         if (!"file://".equals(getProtocol())) {
160             int indexSlash = urlPath.indexOf('/');
161 
162             String hostPort = urlPath;
163 
164             if (indexSlash > 0) {
165                 hostPort = urlPath.substring(0, indexSlash);
166             }
167 
168             int indexColon = hostPort.indexOf(':');
169 
170             if (indexColon > 0) {
171                 setHost(hostPort.substring(0, indexColon));
172                 setPort(Integer.parseInt(hostPort.substring(indexColon + 1)));
173             } else {
174                 setHost(hostPort);
175             }
176         }
177     }
178 
179     /** {@inheritDoc} */
180     public ScmProviderRepository getParent() {
181         String newUrl = getUrl().substring(getProtocol().length());
182 
183         while (newUrl.endsWith("/.")) {
184             newUrl = newUrl.substring(0, newUrl.length() - 2);
185         }
186 
187         while (newUrl.endsWith("/")) {
188             newUrl = newUrl.substring(0, newUrl.length() - 1);
189         }
190 
191         int i = newUrl.lastIndexOf('/');
192 
193         if (i < 0) {
194             return null;
195         }
196         newUrl = newUrl.substring(0, i);
197 
198         return new SvnScmProviderRepository(getProtocol() + newUrl, getUser(), getPassword());
199     }
200 
201     /** {@inheritDoc} */
202     public String getRelativePath(ScmProviderRepository ancestor) {
203         if (ancestor instanceof SvnScmProviderRepository) {
204             SvnScmProviderRepository svnAncestor = (SvnScmProviderRepository) ancestor;
205 
206             String path = getUrl().replaceFirst(svnAncestor.getUrl() + "/", "");
207 
208             if (!path.equals(getUrl())) {
209                 return path;
210             }
211         }
212         return null;
213     }
214 
215     /** {@inheritDoc} */
216     public String toString() {
217         return getUrl();
218     }
219 }