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  public class SvnScmProviderRepository extends ScmProviderRepositoryWithHost {
29      private String url;
30  
31      private String protocol;
32  
33      /**
34       * The base directory for any tags. Can be relative to the repository URL or an absolute URL.
35       */
36      private String tagBase;
37  
38      /**
39       * The base directory for any branches. Can be relative to the repository URL or an absolute URL.
40       */
41      private String branchBase;
42  
43      public SvnScmProviderRepository(String url) {
44          parseUrl(url);
45  
46          tagBase = SvnTagBranchUtils.resolveTagBase(url);
47  
48          branchBase = SvnTagBranchUtils.resolveBranchBase(url);
49      }
50  
51      public SvnScmProviderRepository(String url, String user, String password) {
52          this(url);
53  
54          setUser(user);
55  
56          setPassword(password);
57      }
58  
59      public String getUrl() {
60          return url;
61      }
62  
63      /**
64       * Returns the url/directory to be used when tagging this repository.
65       */
66      public String getTagBase() {
67          return tagBase;
68      }
69  
70      /**
71       * Sets the url/directory to be used when tagging this repository.
72       * The TagBase is a way to override the default tag location for the
73       * repository.  The default tag location is automatically determined
74       * for repositories in the standard subversion layout (with /tags /branches /trunk).
75       * Specify this value only if the repository is using a directory other than "/tags" for tagging.
76       *
77       * @param tagBase an absolute or relative url to the base directory to create tags in.
78       *                URL should be in a format that svn client understands, not the scm url format.
79       */
80      public void setTagBase(String tagBase) {
81          this.tagBase = tagBase;
82      }
83  
84      /**
85       * Returns the url/directory to be used when tagging this repository.
86       */
87      public String getBranchBase() {
88          return branchBase;
89      }
90  
91      /**
92       * Sets the url/directory to be used when branching this repository.
93       * The BranchBase is a way to override the default branch location for the
94       * repository.  The default branch location is automatically determined
95       * for repositories in the standard subversion layout (with /tags /branches /trunk).
96       * Specify this value only if the repository is using a directory other than "/branches" for branching.
97       *
98       * @param branchBase an absolute or relative url to the base directory to create branch in.
99       *                   URL should be in a format that svn client understands, not the scm url format.
100      */
101     public void setBranchBase(String branchBase) {
102         this.branchBase = branchBase;
103     }
104 
105     private void setProtocol(String protocol) {
106         this.protocol = protocol;
107     }
108 
109     /**
110      * Get the protocol used in this repository (file://, http://, https://,...)
111      *
112      * @return the protocol
113      */
114     public String getProtocol() {
115         return protocol;
116     }
117 
118     private void parseUrl(String url) {
119         if (url.startsWith("file")) {
120             setProtocol("file://");
121         } else if (url.startsWith("https")) {
122             setProtocol("https://");
123         } else if (url.startsWith("http")) {
124             setProtocol("http://");
125         } else if (url.startsWith("svn+")) {
126             setProtocol(url.substring(0, url.indexOf("://") + 3));
127         } else if (url.startsWith("svn")) {
128             setProtocol("svn://");
129         }
130 
131         if (getProtocol() == null) {
132             return;
133         }
134 
135         String urlPath = url.substring(getProtocol().length());
136 
137         int indexAt = urlPath.indexOf('@');
138 
139         // a file:// URL may contain userinfo according to RFC 8089, but our implementation is broken
140         // extract user information, broken see SCM-909
141         if (indexAt > 0 && !getProtocol().startsWith("svn+") && !getProtocol().equals("file://")) {
142             String userPassword = urlPath.substring(0, indexAt);
143             if (userPassword.indexOf(':') < 0) {
144                 setUser(userPassword);
145             } else {
146                 setUser(userPassword.substring(0, userPassword.indexOf(':')));
147                 setPassword(userPassword.substring(userPassword.indexOf(':') + 1));
148             }
149 
150             urlPath = urlPath.substring(indexAt + 1);
151 
152             this.url = getProtocol() + urlPath;
153         } else {
154             this.url = getProtocol() + urlPath;
155         }
156 
157         if (!"file://".equals(getProtocol())) {
158             int indexSlash = urlPath.indexOf('/');
159 
160             String hostPort = urlPath;
161 
162             if (indexSlash > 0) {
163                 hostPort = urlPath.substring(0, indexSlash);
164             }
165 
166             int indexColon = hostPort.indexOf(':');
167 
168             if (indexColon > 0) {
169                 setHost(hostPort.substring(0, indexColon));
170                 setPort(Integer.parseInt(hostPort.substring(indexColon + 1)));
171             } else {
172                 setHost(hostPort);
173             }
174         }
175     }
176 
177     /**
178      * {@inheritDoc}
179      */
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     /**
202      * {@inheritDoc}
203      */
204     public String getRelativePath(ScmProviderRepository ancestor) {
205         if (ancestor instanceof SvnScmProviderRepository) {
206             SvnScmProviderRepository svnAncestor = (SvnScmProviderRepository) ancestor;
207 
208             String path = getUrl().replaceFirst(svnAncestor.getUrl() + "/", "");
209 
210             if (!path.equals(getUrl())) {
211                 return path;
212             }
213         }
214         return null;
215     }
216 
217     /**
218      * {@inheritDoc}
219      */
220     public String toString() {
221         return getUrl();
222     }
223 }