001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2013 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 */
020package org.sonar.api.resources;
021
022import org.apache.commons.lang.StringUtils;
023import org.apache.commons.lang.builder.ToStringBuilder;
024import org.sonar.api.scan.filesystem.PathResolver;
025import org.sonar.api.utils.WildcardPattern;
026
027import java.io.File;
028import java.util.List;
029
030/**
031 * A class that represents a Java class. This class can either be a Test class or source class
032 *
033 * @since 1.10
034 * @deprecated since 4.2 use {@link org.sonar.api.resources.File}
035 */
036@Deprecated
037public class JavaFile extends Resource {
038
039  private static final String JAVA_SUFFIX = ".java";
040  private static final String JAV_SUFFIX = ".jav";
041  private String className;
042  private String filename;
043  private String fullyQualifiedName;
044  private String packageFullyQualifiedName;
045  private boolean unitTest;
046  private JavaPackage parent;
047
048  private JavaFile() {
049    // Default constructor
050  }
051
052  /**
053   * Creates a JavaFile that is not a class of test based on package and file names
054   */
055  public JavaFile(String packageName, String className) {
056    this(packageName, className, false);
057  }
058
059  /**
060   * Creates a JavaFile that can be of any type based on package and file names
061   *
062   * @param unitTest whether it is a unit test file or a source file
063   */
064  public JavaFile(String packageKey, String className, boolean unitTest) {
065    if (className == null) {
066      throw new IllegalArgumentException("Java filename can not be null");
067    }
068    this.className = StringUtils.trim(className);
069    String deprecatedKey;
070    if (StringUtils.isBlank(packageKey)) {
071      this.packageFullyQualifiedName = JavaPackage.DEFAULT_PACKAGE_NAME;
072      this.fullyQualifiedName = this.className;
073      deprecatedKey = new StringBuilder().append(this.packageFullyQualifiedName).append(".").append(this.className).toString();
074    } else {
075      this.packageFullyQualifiedName = packageKey.trim();
076      deprecatedKey = new StringBuilder().append(this.packageFullyQualifiedName).append(".").append(this.className).toString();
077      this.fullyQualifiedName = deprecatedKey;
078    }
079    setDeprecatedKey(deprecatedKey);
080    this.unitTest = unitTest;
081  }
082
083  /**
084   * Creates a source file from its key
085   */
086  public JavaFile(String deprecatedKey) {
087    this(deprecatedKey, false);
088  }
089
090  /**
091   * Creates any JavaFile from its key
092   *
093   * @param unitTest whether it is a unit test file or a source file
094   */
095  public JavaFile(String deprecatedKey, boolean unitTest) {
096    if (deprecatedKey == null) {
097      throw new IllegalArgumentException("Java filename can not be null");
098    }
099    String realKey = StringUtils.trim(deprecatedKey);
100    this.unitTest = unitTest;
101
102    if (realKey.contains(".")) {
103      this.className = StringUtils.substringAfterLast(realKey, ".");
104      this.packageFullyQualifiedName = StringUtils.substringBeforeLast(realKey, ".");
105      this.fullyQualifiedName = realKey;
106
107    } else {
108      this.className = realKey;
109      this.fullyQualifiedName = realKey;
110      this.packageFullyQualifiedName = JavaPackage.DEFAULT_PACKAGE_NAME;
111      realKey = new StringBuilder().append(JavaPackage.DEFAULT_PACKAGE_NAME).append(".").append(realKey).toString();
112    }
113    setDeprecatedKey(realKey);
114  }
115
116  /**
117   * {@inheritDoc}
118   */
119  @Override
120  public JavaPackage getParent() {
121    if (parent == null) {
122      parent = new JavaPackage(packageFullyQualifiedName);
123    }
124    return parent;
125  }
126
127  /**
128   * @return null
129   */
130  @Override
131  public String getDescription() {
132    return null;
133  }
134
135  /**
136   * @return Java
137   */
138  @Override
139  public Language getLanguage() {
140    return Java.INSTANCE;
141  }
142
143  /**
144   * {@inheritDoc}
145   */
146  @Override
147  public String getName() {
148    return StringUtils.isNotBlank(filename) ? filename : (className + JAVA_SUFFIX);
149  }
150
151  /**
152   * {@inheritDoc}
153   */
154  @Override
155  public String getLongName() {
156    return fullyQualifiedName;
157  }
158
159  /**
160   * @return SCOPE_ENTITY
161   */
162  @Override
163  public String getScope() {
164    return Scopes.FILE;
165  }
166
167  /**
168   * @return QUALIFIER_UNIT_TEST_CLASS or QUALIFIER_FILE depending whether it is a unit test class
169   */
170  @Override
171  public String getQualifier() {
172    return unitTest ? Qualifiers.UNIT_TEST_FILE : Qualifiers.FILE;
173  }
174
175  /**
176   * @return whether the JavaFile is a unit test class or not
177   */
178  public boolean isUnitTest() {
179    return unitTest;
180  }
181
182  /**
183   * {@inheritDoc}
184   */
185  @Override
186  public boolean matchFilePattern(String antPattern) {
187    WildcardPattern matcher = WildcardPattern.create(antPattern, Directory.SEPARATOR);
188    return matcher.match(getKey());
189  }
190
191  public static JavaFile fromIOFile(File file, Project module, boolean unitTest) {
192    if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), JAVA_SUFFIX)) {
193      return null;
194    }
195    PathResolver.RelativePath relativePath = new PathResolver().relativePath(
196      unitTest ? module.getFileSystem().getTestDirs() : module.getFileSystem().getSourceDirs(),
197      file);
198    if (relativePath != null) {
199      JavaFile sonarFile = fromRelativePath(relativePath.path(), unitTest);
200      sonarFile.setPath(new PathResolver().relativePath(module.getFileSystem().getBasedir(), file));
201      return sonarFile;
202    }
203    return null;
204  }
205
206  /**
207   * For internal use only.
208   */
209  public static JavaFile create(String relativePathFromBasedir) {
210    JavaFile javaFile = new JavaFile();
211    String normalizedPath = normalize(relativePathFromBasedir);
212    javaFile.setKey(normalizedPath);
213    javaFile.setPath(normalizedPath);
214    javaFile.parent = new JavaPackage();
215    String directoryPath;
216    if (normalizedPath != null && normalizedPath.contains(Directory.SEPARATOR)) {
217      directoryPath = StringUtils.substringBeforeLast(normalizedPath, Directory.SEPARATOR);
218    } else {
219      directoryPath = Directory.SEPARATOR;
220    }
221    String normalizedParentPath = normalize(directoryPath);
222    javaFile.parent.setKey(normalizedParentPath);
223    javaFile.parent.setPath(normalizedParentPath);
224    return javaFile;
225  }
226
227  /**
228   * For internal use only.
229   */
230  public static JavaFile create(String relativePathFromBasedir, String relativePathFromSourceDir, boolean unitTest) {
231    JavaFile javaFile = JavaFile.create(relativePathFromBasedir);
232    if (relativePathFromSourceDir.contains(Directory.SEPARATOR)) {
233      javaFile.packageFullyQualifiedName = StringUtils.substringBeforeLast(relativePathFromSourceDir, Directory.SEPARATOR);
234      javaFile.packageFullyQualifiedName = StringUtils.replace(javaFile.packageFullyQualifiedName, Directory.SEPARATOR, ".");
235      javaFile.filename = StringUtils.substringAfterLast(relativePathFromSourceDir, Directory.SEPARATOR);
236      if (javaFile.filename.endsWith(JAVA_SUFFIX)) {
237        javaFile.className = StringUtils.removeEndIgnoreCase(javaFile.filename, JAVA_SUFFIX);
238      } else if (javaFile.filename.endsWith(JAV_SUFFIX)) {
239        javaFile.className = StringUtils.removeEndIgnoreCase(javaFile.filename, JAV_SUFFIX);
240      }
241      javaFile.fullyQualifiedName = javaFile.packageFullyQualifiedName + "." + javaFile.className;
242      javaFile.setDeprecatedKey(javaFile.fullyQualifiedName);
243      javaFile.parent.setDeprecatedKey(Directory.parseKey(StringUtils.substringBeforeLast(relativePathFromSourceDir, Directory.SEPARATOR)));
244    } else {
245      javaFile.packageFullyQualifiedName = JavaPackage.DEFAULT_PACKAGE_NAME;
246      javaFile.className = StringUtils.removeEndIgnoreCase(relativePathFromSourceDir, JAVA_SUFFIX);
247      javaFile.fullyQualifiedName = javaFile.className;
248      javaFile.setDeprecatedKey(JavaPackage.DEFAULT_PACKAGE_NAME + "." + javaFile.className);
249      javaFile.parent.setDeprecatedKey(Directory.ROOT);
250    }
251    javaFile.unitTest = unitTest;
252    return javaFile;
253  }
254
255  /**
256   * @deprecated since 4.2 use {@link #create(String, String, boolean)}
257   */
258  @Deprecated
259  public static JavaFile fromRelativePath(String relativePath, boolean unitTest) {
260    if (relativePath != null) {
261      String pacname = null;
262      String classname = relativePath;
263
264      if (relativePath.indexOf('/') >= 0) {
265        pacname = StringUtils.substringBeforeLast(relativePath, "/");
266        pacname = StringUtils.replace(pacname, "/", ".");
267        classname = StringUtils.substringAfterLast(relativePath, "/");
268      }
269      classname = StringUtils.substringBeforeLast(classname, ".");
270      return new JavaFile(pacname, classname, unitTest);
271    }
272    return null;
273  }
274
275  /**
276   * Creates a JavaFile from a file in the source directories
277   *
278   * @return the JavaFile created if exists, null otherwise
279   * @deprecated since 4.2 use {@link #create(String, String, boolean)}
280   */
281  @Deprecated
282  public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) {
283    if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), JAVA_SUFFIX)) {
284      return null;
285    }
286    PathResolver.RelativePath relativePath = new PathResolver().relativePath(sourceDirs, file);
287    if (relativePath != null) {
288      return fromRelativePath(relativePath.path(), unitTest);
289    }
290    return null;
291  }
292
293  /**
294   * Shortcut to fromIOFile with an abolute path
295   * @deprecated since 4.2 use {@link #create(String, String, boolean)}
296   */
297  @Deprecated
298  public static JavaFile fromAbsolutePath(String path, List<File> sourceDirs, boolean unitTest) {
299    if (path == null) {
300      return null;
301    }
302    return fromIOFile(new File(path), sourceDirs, unitTest);
303  }
304
305  @Override
306  public String toString() {
307    return new ToStringBuilder(this)
308      .append("key", getKey())
309      .append("deprecatedKey", getDeprecatedKey())
310      .append("path", getPath())
311      .append("filename", className)
312      .toString();
313  }
314
315}