001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * SonarQube is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.api.resources;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.apache.commons.lang.builder.ToStringBuilder;
024    import org.sonar.api.batch.SensorContext;
025    import org.sonar.api.scan.filesystem.PathResolver;
026    import org.sonar.api.utils.WildcardPattern;
027    
028    import javax.annotation.CheckForNull;
029    
030    /**
031     * @since 1.10
032     */
033    public class Directory extends Resource {
034    
035      public static final String SEPARATOR = "/";
036      public static final String ROOT = "[root]";
037    
038      Directory() {
039        // Used by factory
040      }
041    
042      /**
043       * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
044       */
045      @Deprecated
046      public Directory(String relativePathFromSourceDir) {
047        this(relativePathFromSourceDir, null);
048      }
049    
050      /**
051       * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
052       */
053      @Deprecated
054      public Directory(String relativePathFromSourceDir, Language language) {
055        setDeprecatedKey(parseKey(relativePathFromSourceDir));
056      }
057    
058      @Override
059      public String getName() {
060        return getKey();
061      }
062    
063      @Override
064      public String getLongName() {
065        return null;
066      }
067    
068      @Override
069      public String getDescription() {
070        return null;
071      }
072    
073      @Override
074      public Language getLanguage() {
075        return null;
076      }
077    
078      @Override
079      public String getScope() {
080        return Scopes.DIRECTORY;
081      }
082    
083      @Override
084      public String getQualifier() {
085        return Qualifiers.DIRECTORY;
086      }
087    
088      @Override
089      public Resource getParent() {
090        return null;
091      }
092    
093      @Override
094      public boolean matchFilePattern(String antPattern) {
095        WildcardPattern matcher = WildcardPattern.create(antPattern, "/");
096        return matcher.match(getKey());
097      }
098    
099      public static String parseKey(String key) {
100        if (StringUtils.isBlank(key)) {
101          return ROOT;
102        }
103        String normalizedKey = key;
104        normalizedKey = normalizedKey.replace('\\', '/');
105        normalizedKey = StringUtils.trim(normalizedKey);
106        normalizedKey = StringUtils.removeStart(normalizedKey, Directory.SEPARATOR);
107        normalizedKey = StringUtils.removeEnd(normalizedKey, Directory.SEPARATOR);
108        return normalizedKey;
109      }
110    
111      /**
112       * Creates a {@link Directory} from an absolute {@link java.io.File} and a module.
113       * The returned {@link Directory} can be then passed for example to
114       * {@link SensorContext#saveMeasure(Resource, org.sonar.api.measures.Measure)}.
115       * @param dir absolute path to a directory
116       * @param module
117       * @return null if the directory is not under module basedir.
118       * @since 4.2
119       */
120      @CheckForNull
121      public static Directory fromIOFile(java.io.File dir, Project module) {
122        String relativePathFromBasedir = new PathResolver().relativePath(module.getFileSystem().getBasedir(), dir);
123        if (relativePathFromBasedir != null) {
124          return Directory.create(relativePathFromBasedir);
125        }
126        return null;
127      }
128    
129      /**
130       * Create a Directory that is partially initialized. But that's enough to call for example
131       * {@link SensorContext#saveMeasure(Resource, org.sonar.api.measures.Measure)} when resources are already indexed.
132       * Internal use only.
133       */
134      public static Directory create(String relativePathFromBaseDir) {
135        Directory d = new Directory();
136        String normalizedPath = normalize(relativePathFromBaseDir);
137        d.setKey(normalizedPath);
138        d.setPath(normalizedPath);
139        return d;
140      }
141    
142      /**
143       * Create a directory that is fully initialized. Use for indexing resources.
144       * Internal use only.
145       * @since 4.2
146       */
147      public static Directory create(String relativePathFromBaseDir, String relativePathFromSourceDir) {
148        Directory d = Directory.create(relativePathFromBaseDir);
149        d.setDeprecatedKey(parseKey(relativePathFromSourceDir));
150        return d;
151      }
152    
153      @Override
154      public String toString() {
155        return new ToStringBuilder(this)
156          .append("key", getKey())
157          .append("deprecatedKey", getDeprecatedKey())
158          .append("path", getPath())
159          .toString();
160      }
161    
162    }