View Javadoc
1   package org.apache.maven.scm.provider.clearcase.repository;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.scm.log.ScmLogger;
23  import org.apache.maven.scm.provider.ScmProviderRepository;
24  import org.apache.maven.scm.providers.clearcase.settings.Settings;
25  import org.apache.maven.scm.repository.ScmRepositoryException;
26  
27  import java.io.File;
28  import java.net.InetAddress;
29  import java.net.MalformedURLException;
30  import java.net.URI;
31  import java.net.URISyntaxException;
32  import java.net.URL;
33  import java.net.UnknownHostException;
34  import java.util.StringTokenizer;
35  
36  /**
37   * Provider Repository for ClearCase (standard, LT, UCM)
38   * <p />
39   * Url format for ClearCase and ClearCaseLT : <br />
40   * [view_name]:[configspec] or [view_name]|[configspec]
41   * <p />
42   * Url format for ClearCaseUCM : <br />
43   * [view_name]|[configspec]|[vob_name]|[stream_name] or [view_name]:[configspec]:[vob_name]:[stream_name]
44   * <p />
45   * [configspec] can be used in two different ways:
46   * <ul>
47   * <li>Path to a config spec file that is
48   * used when creating the snapshot view, e.g.
49   * "\\myserver\clearcase\configspecs\my_module.txt", or:</li>
50   * <li>A load rule that is used to automatically create a config spec, e.g. "load /MY_VOB/my/project/dir"</li>
51   * </ul>
52   * Notice that checking out from a tag is currently only supported when the second option is used.
53   *
54   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
55   * @version $Id: ClearCaseScmProviderRepository.java 483105 2006-12-06 15:07:54Z
56   *          evenisse $
57   */
58  public class ClearCaseScmProviderRepository
59      extends ScmProviderRepository
60  {
61      private ScmLogger logger;
62  
63      private boolean viewNameGivenByUser = false;
64  
65      private String viewName;
66  
67      /**
68       * The user-specified config spec; may be null.
69       */
70      private File configSpec;
71  
72      /**
73       * The directory to be loaded, when auto-generating the config spec.
74       */
75      private String loadDirectory;
76  
77      /**
78       * Describe the stream linked to the view. Only used with ClearCaseUCM
79       */
80      private String streamName;
81  
82      /**
83       * Describe the vob containing the stream. Only used with ClearCaseUCM
84       */
85      private String vobName;
86  
87      /**
88       * Provider configuration settings
89       */
90      private Settings settings;
91  
92      /**
93       * Describe the Element Name
94       */
95      private String elementName;
96  
97      /**
98       * Define the flag used in the clearcase-settings.xml when using ClearCaseLT
99       */
100     public static final String CLEARCASE_LT = "LT";
101 
102     /**
103      * Define the flag used in the clearcase-settings.xml when using ClearCaseUCM
104      */
105     public static final String CLEARCASE_UCM = "UCM";
106 
107     /**
108      * Define the default value from the clearcase-settings.xml when using ClearCase
109      */
110     public static final String CLEARCASE_DEFAULT = null;
111 
112     public ClearCaseScmProviderRepository( ScmLogger logger, String url, Settings settings )
113         throws ScmRepositoryException
114     {
115         this.logger = logger;
116         this.settings = settings;
117         try
118         {
119             parseUrl( url );
120         }
121         catch ( MalformedURLException e )
122         {
123             throw new ScmRepositoryException( "Illegal URL: " + url + "(" + e.getMessage() + ")" );
124         }
125         catch ( URISyntaxException e )
126         {
127             throw new ScmRepositoryException( "Illegal URL: " + url + "(" + e.getMessage() + ")" );
128         }
129         catch ( UnknownHostException e )
130         {
131             throw new ScmRepositoryException( "Illegal URL: " + url + "(" + e.getMessage() + ")" );
132         }
133     }
134 
135     private void parseUrl( String url )
136         throws MalformedURLException, URISyntaxException, UnknownHostException
137     {
138         if ( url.indexOf( '|' ) != -1 )
139         {
140             StringTokenizer tokenizer = new StringTokenizer( url, "|" );
141             fillInProperties( tokenizer );
142         }
143         else
144         {
145             StringTokenizer tokenizer = new StringTokenizer( url, ":" );
146             fillInProperties( tokenizer );
147         }
148     }
149 
150     private void fillInProperties( StringTokenizer tokenizer )
151         throws UnknownHostException, URISyntaxException, MalformedURLException
152     {
153         String configSpecString = null;
154 
155         if ( CLEARCASE_UCM.equals( settings.getClearcaseType() ) )
156         {
157             configSpecString = fillUCMProperties( tokenizer );
158         }
159         else
160         {
161             configSpecString = fillDefaultProperties( tokenizer );
162         }
163 
164         if ( !configSpecString.startsWith( "load " ) )
165         {
166             configSpec = createConfigSpecFile( configSpecString );
167             loadDirectory = null;
168         }
169         else
170         {
171             configSpec = null;
172             loadDirectory = configSpecString.substring( 5 );
173 
174         }
175     }
176 
177     private String fillDefaultProperties( StringTokenizer tokenizer )
178         throws UnknownHostException
179     {
180         int tokenNumber = tokenizer.countTokens();
181         String configSpecString;
182         if ( tokenNumber == 1 )
183         {
184             // No view name was given
185             viewName = getDefaultViewName();
186             configSpecString = tokenizer.nextToken();
187         }
188         else
189         {
190             configSpecString = checkViewName( tokenizer );
191             checkUnexpectedParameter( tokenizer, tokenNumber, 2 );
192         }
193         if ( logger.isDebugEnabled() )
194         {
195             logger.debug( "viewName = '" + viewName + "' ; configSpec = '" + configSpecString + "'" );
196         }
197         return configSpecString;
198     }
199 
200     private String fillUCMProperties( StringTokenizer tokenizer )
201         throws UnknownHostException, MalformedURLException
202     {
203         int tokenNumber = tokenizer.countTokens();
204         if ( tokenNumber <= 2 )
205         {
206             throw new MalformedURLException( "ClearCaseUCM need more parameters. Expected url format : "
207                 + "[view_name]|[configspec]|[vob_name]|[stream_name]" );
208         }
209 
210         String configSpecString;
211         if ( tokenNumber == 3 )
212         {
213             // No view name was given
214             viewName = getDefaultViewName();
215             configSpecString = tokenizer.nextToken();
216             vobName = tokenizer.nextToken();
217             streamName = tokenizer.nextToken();
218         }
219         else if ( tokenNumber == 4 )
220         {
221             String[] tokens = new String[4];
222             tokens[0] = tokenizer.nextToken();
223             tokens[1] = tokenizer.nextToken();
224             tokens[2] = tokenizer.nextToken();
225             tokens[3] = tokenizer.nextToken();
226 
227             if ( tokens[3].startsWith( "/main/" ) )
228             {
229                 viewName = getDefaultViewName();
230                 configSpecString = tokens[0];
231                 vobName = tokens[1];
232                 streamName = tokens[2];
233                 elementName = tokens[3];
234             }
235             else
236             {
237                 viewName = tokens[0];
238                 viewNameGivenByUser = true;
239                 configSpecString = tokens[1];
240                 vobName = tokens[2];
241                 streamName = tokens[3];
242             }
243         }
244         else
245         {
246             configSpecString = checkViewName( tokenizer );
247             vobName = tokenizer.nextToken();
248             streamName = tokenizer.nextToken();
249             elementName = tokenizer.nextToken();
250             checkUnexpectedParameter( tokenizer, tokenNumber, 5 );
251         }
252 
253         if ( logger.isInfoEnabled() )
254         {
255             logger.info( "viewName = '" + viewName + "' ; configSpec = '" + configSpecString + "' ; vobName = '"
256                 + vobName + "' ; streamName = '" + streamName + "' ; elementName = '" + elementName + "'" );
257         }
258 
259         return configSpecString;
260     }
261 
262     private String checkViewName( StringTokenizer tokenizer )
263         throws UnknownHostException
264     {
265         viewName = tokenizer.nextToken();
266         if ( viewName.length() > 0 )
267         {
268             viewNameGivenByUser = true;
269         }
270         else
271         {
272             viewName = getDefaultViewName();
273         }
274 
275         return tokenizer.nextToken();
276     }
277 
278     private void checkUnexpectedParameter( StringTokenizer tokenizer, int tokenNumber, int maxTokenNumber )
279     {
280         if ( tokenNumber > maxTokenNumber )
281         {
282             String unexpectedToken = tokenizer.nextToken();
283             if ( logger.isInfoEnabled() )
284             {
285                 logger.info( "The SCM URL contains unused parameter : " + unexpectedToken );
286             }
287         }
288     }
289 
290     private File createConfigSpecFile( String spec )
291         throws URISyntaxException, MalformedURLException
292     {
293         File result;
294         if ( spec.indexOf( ':' ) == -1 )
295         {
296             result = new File( spec );
297         }
298         else
299         {
300             result = new File( new URI( new URL( spec ).toString() ) );
301         }
302         return result;
303     }
304 
305     /**
306      * Default: ${hostname}-{user.name}-maven
307      *
308      * @return the default view name
309      */
310     private String getDefaultViewName()
311         throws UnknownHostException
312     {
313         String username = System.getProperty( "user.name", "nouser" );
314         String hostname = getHostName();
315         return username + "-" + hostname + "-maven";
316     }
317 
318     private String getHostName()
319         throws UnknownHostException
320     {
321         return InetAddress.getLocalHost().getHostName();
322     }
323 
324     /**
325      * Returns the name of the view. If it is defined in the scm url, then it is returned as defined there.
326      * If it is the default name, then the uniqueId is added
327      *
328      * @param uniqueId
329      * @return the name of the view
330      */
331     public String getViewName( String uniqueId )
332     {
333         String result;
334         if ( viewNameGivenByUser )
335         {
336             result = viewName;
337         }
338         else
339         {
340             result = viewName + "-" + uniqueId;
341         }
342 
343         return result;
344     }
345 
346     /**
347      * Returns the user-supplied config spec or <code>null</code> in case it
348      * should be automatically generated
349      *
350      * @return File or <code>null</code>
351      * @see #isAutoConfigSpec()
352      */
353     public File getConfigSpec()
354     {
355         return configSpec;
356     }
357 
358     /**
359      * Returns true when the config spec has not been supplied by the user, but
360      * instead should automatically be generated by the plugin
361      *
362      * @return true if auto config spec
363      */
364     public boolean isAutoConfigSpec()
365     {
366         return configSpec == null;
367     }
368 
369     /**
370      * Returns the VOB directory to be loaded when auto-generating the config
371      * spec.
372      *
373      * @return <code>null</code> when isAutoConfigSpec() returns false;
374      *         otherwise the VOB directory
375      */
376     public String getLoadDirectory()
377     {
378         return loadDirectory;
379     }
380 
381     public String getStreamName()
382     {
383         return streamName;
384     }
385 
386     public String getVobName()
387     {
388         return vobName;
389     }
390 
391     public String getElementName()
392     {
393         return elementName;
394     }
395 
396     public boolean hasElements()
397     {
398         if ( elementName == null )
399         {
400             return false;
401         }
402 
403         return true;
404     }
405 }