@@ -73,6 +73,7 @@ public final class SourceScanner implements Sensor { | |||
protected void parseDirs(Project project, boolean isTest) { | |||
Charset sourcesEncoding = fileSystem.sourceCharset(); | |||
// TODO use InputFile | |||
List<File> files; | |||
List<File> dirs; | |||
if (isTest) { | |||
@@ -85,6 +86,7 @@ public final class SourceScanner implements Sensor { | |||
for (File inputFile : files) { | |||
try { | |||
// TODO reuse InputFile.attribute(DefaultInputFile.COMPONENT_KEY ? | |||
String componentKey = resolveComponent(inputFile, dirs, project, isTest); | |||
if (componentKey != null) { | |||
@@ -29,7 +29,7 @@ import org.sonar.batch.events.EventBus; | |||
import org.sonar.batch.index.DefaultIndex; | |||
import org.sonar.batch.index.PersistenceManager; | |||
import org.sonar.batch.index.ScanPersister; | |||
import org.sonar.batch.scan.JsonReport; | |||
import org.sonar.batch.scan.report.JsonReport; | |||
import org.sonar.batch.scan.filesystem.FileSystemLogger; | |||
import org.sonar.batch.scan.maven.MavenPhaseExecutor; | |||
import org.sonar.batch.scan.maven.MavenPluginsConfigurator; |
@@ -31,7 +31,7 @@ import org.sonar.api.batch.maven.DependsUponMavenPlugin; | |||
import org.sonar.api.batch.maven.MavenPluginHandler; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.batch.events.EventBus; | |||
import org.sonar.batch.scan.DeprecatedJsonReport; | |||
import org.sonar.batch.scan.report.DeprecatedJsonReport; | |||
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; | |||
import org.sonar.batch.scan.maven.MavenPluginExecutor; | |||
@@ -49,6 +49,9 @@ import org.sonar.batch.issue.ModuleIssues; | |||
import org.sonar.batch.phases.PhaseExecutor; | |||
import org.sonar.batch.phases.PhasesTimeProfiler; | |||
import org.sonar.batch.scan.filesystem.*; | |||
import org.sonar.batch.scan.report.ComponentSelectorFactory; | |||
import org.sonar.batch.scan.report.DeprecatedJsonReport; | |||
import org.sonar.batch.scan.report.JsonReport; | |||
import org.sonar.core.component.ScanPerspectives; | |||
import org.sonar.core.measure.MeasurementFilters; | |||
@@ -116,9 +119,13 @@ public class ModuleScanContainer extends ComponentContainer { | |||
IssueFilters.class, | |||
MeasurementFilters.class, | |||
ResourceFilters.class, | |||
new ProfileProvider(), | |||
// report | |||
DeprecatedJsonReport.class, | |||
JsonReport.class, | |||
new ProfileProvider(), | |||
ComponentSelectorFactory.class, | |||
// issues | |||
IssuableFactory.class, |
@@ -28,6 +28,9 @@ import org.apache.commons.lang.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.resources.JavaFile; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.InputFileFilter; | |||
import org.sonar.api.scan.filesystem.ModuleFileSystem; | |||
@@ -66,18 +69,21 @@ public class FileIndex implements BatchComponent { | |||
private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter("."))); | |||
private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE; | |||
private final PathResolver pathResolver = new PathResolver(); | |||
private final PathResolver pathResolver; | |||
private final List<InputFileFilter> filters; | |||
private final LanguageRecognizer languageRecognizer; | |||
private final InputFileCache cache; | |||
private final FileHashes fileHashes; | |||
private final Project project; | |||
public FileIndex(List<InputFileFilter> filters, LanguageRecognizer languageRecognizer, | |||
InputFileCache cache, FileHashes fileHashes) { | |||
InputFileCache cache, FileHashes fileHashes, PathResolver pathResolver, Project project) { | |||
this.filters = filters; | |||
this.languageRecognizer = languageRecognizer; | |||
this.cache = cache; | |||
this.fileHashes = fileHashes; | |||
this.pathResolver = pathResolver; | |||
this.project = project; | |||
} | |||
void index(DefaultModuleFileSystem fileSystem) { | |||
@@ -168,7 +174,14 @@ public class FileIndex implements BatchComponent { | |||
// paths | |||
set(attributes, InputFile.ATTRIBUTE_SOURCEDIR_PATH, PathUtils.canonicalPath(sourceDir)); | |||
set(attributes, InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, pathResolver.relativePath(sourceDir, file)); | |||
String sourceRelativePath = pathResolver.relativePath(sourceDir, file); | |||
set(attributes, InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, sourceRelativePath); | |||
if (Java.KEY.equals(lang)) { | |||
set(attributes, DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, project.getEffectiveKey() + ":" + JavaFile.fromRelativePath(sourceRelativePath, false).getKey()); | |||
} else { | |||
set(attributes, DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, project.getEffectiveKey() + ":" + sourceRelativePath); | |||
} | |||
// hash + status | |||
initStatus(file, fileSystem.sourceCharset(), path, attributes); |
@@ -0,0 +1,34 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.report; | |||
import org.sonar.api.issue.Issue; | |||
import java.util.Set; | |||
abstract class ComponentSelector { | |||
abstract void init(); | |||
abstract boolean register(Issue issue); | |||
abstract Set<String> componentKeys(); | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.report; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.batch.scan.filesystem.InputFileCache; | |||
public class ComponentSelectorFactory implements BatchComponent { | |||
private final InputFileCache fileCache; | |||
private final Settings settings; | |||
public ComponentSelectorFactory(InputFileCache fileCache, Settings settings) { | |||
this.fileCache = fileCache; | |||
this.settings = settings; | |||
} | |||
public ComponentSelector create() { | |||
if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW)) { | |||
return new IncrementalComponentSelector(fileCache); | |||
} | |||
return new DefaultComponentSelector(); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.report; | |||
import org.sonar.api.issue.Issue; | |||
import java.util.Set; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
class DefaultComponentSelector extends ComponentSelector{ | |||
private final Set<String> componentKeys = newHashSet(); | |||
@Override | |||
void init() { | |||
} | |||
@Override | |||
boolean register(Issue issue) { | |||
componentKeys.add(issue.componentKey()); | |||
return true; | |||
} | |||
@Override | |||
Set<String> componentKeys() { | |||
return componentKeys; | |||
} | |||
} |
@@ -17,7 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan; | |||
package org.sonar.batch.scan.report; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.io.Closeables; | |||
@@ -44,7 +44,7 @@ import java.util.Collection; | |||
import java.util.Locale; | |||
/** | |||
* Used by Eclipse until version 3.1. Eclipse 3.2 uses issues exported by {@link org.sonar.batch.scan.JsonReport}. | |||
* Used by Eclipse until version 3.1. Eclipse 3.2 uses issues exported by {@link org.sonar.batch.scan.report.JsonReport}. | |||
* | |||
* @since 3.4 | |||
* @deprecated in 3.6. Replaced by issues. |
@@ -0,0 +1,62 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.report; | |||
import org.sonar.api.issue.Issue; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import org.sonar.batch.scan.filesystem.InputFileCache; | |||
import java.util.Set; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
class IncrementalComponentSelector extends ComponentSelector { | |||
private final InputFileCache cache; | |||
private final Set<String> componentKeys = newHashSet(); | |||
IncrementalComponentSelector(InputFileCache cache) { | |||
this.cache = cache; | |||
} | |||
@Override | |||
void init() { | |||
for (InputFile inputFile : cache.all()) { | |||
String status = inputFile.attribute(InputFile.ATTRIBUTE_STATUS); | |||
if (status != null && !InputFile.STATUS_SAME.equals(status)) { | |||
String componentKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); | |||
if (componentKey != null) { | |||
componentKeys.add(componentKey); | |||
} | |||
} | |||
} | |||
} | |||
@Override | |||
boolean register(Issue issue) { | |||
return componentKeys.contains(issue.componentKey()); | |||
} | |||
@Override | |||
Set<String> componentKeys() { | |||
return componentKeys; | |||
} | |||
} |
@@ -17,8 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan; | |||
package org.sonar.batch.scan.report; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.io.Closeables; | |||
@@ -39,11 +38,7 @@ import org.sonar.batch.events.EventBus; | |||
import org.sonar.batch.issue.IssueCache; | |||
import org.sonar.core.i18n.RuleI18nManager; | |||
import java.io.BufferedWriter; | |||
import java.io.File; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
import java.io.Writer; | |||
import java.io.*; | |||
import java.util.Locale; | |||
import java.util.Set; | |||
@@ -61,15 +56,24 @@ public class JsonReport implements BatchComponent { | |||
private final Server server; | |||
private final RuleI18nManager ruleI18nManager; | |||
private final IssueCache issueCache; | |||
private EventBus eventBus; | |||
private final EventBus eventBus; | |||
private final ComponentSelector componentSelector; | |||
public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, | |||
EventBus eventBus, ComponentSelectorFactory componentSelectorFactory) { | |||
this(settings, fileSystem, server, ruleI18nManager, issueCache, eventBus, componentSelectorFactory.create()); | |||
} | |||
public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, EventBus eventBus) { | |||
@VisibleForTesting | |||
JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, | |||
EventBus eventBus, ComponentSelector componentSelector) { | |||
this.settings = settings; | |||
this.fileSystem = fileSystem; | |||
this.server = server; | |||
this.ruleI18nManager = ruleI18nManager; | |||
this.issueCache = issueCache; | |||
this.eventBus = eventBus; | |||
this.componentSelector = componentSelector; | |||
} | |||
public void execute() { | |||
@@ -90,7 +94,7 @@ public class JsonReport implements BatchComponent { | |||
writeJson(output); | |||
} catch (IOException e) { | |||
throw new SonarException("Unable to write report results in file " + exportFile.getAbsolutePath(), e); | |||
throw new IllegalStateException("Unable to write report results in file " + exportFile.getAbsolutePath(), e); | |||
} finally { | |||
Closeables.closeQuietly(output); | |||
} | |||
@@ -106,9 +110,9 @@ public class JsonReport implements BatchComponent { | |||
json.name("version").value(server.getVersion()); | |||
Set<RuleKey> ruleKeys = newHashSet(); | |||
Set<String> componentKeys = newHashSet(); | |||
writeJsonIssues(json, ruleKeys, componentKeys); | |||
writeJsonComponents(json, componentKeys); | |||
componentSelector.init(); | |||
writeJsonIssues(json, ruleKeys); | |||
writeJsonComponents(json); | |||
writeJsonRules(json, ruleKeys); | |||
json.endObject().flush(); | |||
@@ -119,10 +123,10 @@ public class JsonReport implements BatchComponent { | |||
} | |||
} | |||
private void writeJsonIssues(JsonWriter json, Set<RuleKey> ruleKeys, Set<String> componentKeys) throws IOException { | |||
private void writeJsonIssues(JsonWriter json, Set<RuleKey> ruleKeys) throws IOException { | |||
json.name("issues").beginArray(); | |||
for (DefaultIssue issue : getIssues()) { | |||
if (issue.resolution() == null) { | |||
if (issue.resolution() == null && componentSelector.register(issue)) { | |||
json | |||
.beginObject() | |||
.name("key").value(issue.key()) | |||
@@ -147,21 +151,18 @@ public class JsonReport implements BatchComponent { | |||
json.name("closeDate").value(DateUtils.formatDateTime(issue.closeDate())); | |||
} | |||
json.endObject(); | |||
componentKeys.add(issue.componentKey()); | |||
ruleKeys.add(issue.ruleKey()); | |||
} | |||
} | |||
json.endArray(); | |||
} | |||
private void writeJsonComponents(JsonWriter json, Set<String> componentKeys) throws IOException { | |||
private void writeJsonComponents(JsonWriter json) throws IOException { | |||
json.name("components").beginArray(); | |||
for (String componentKey : componentKeys) { | |||
for (String componentKey : componentSelector.componentKeys()) { | |||
json | |||
.beginObject() | |||
.name("key").value(componentKey) | |||
// module | |||
// path | |||
.endObject(); | |||
} | |||
json.endArray(); |
@@ -0,0 +1,23 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.batch.scan.report; | |||
import javax.annotation.ParametersAreNonnullByDefault; |
@@ -26,7 +26,7 @@ import org.sonar.api.batch.PostJob; | |||
import org.sonar.api.batch.SensorContext; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.batch.events.EventBus; | |||
import org.sonar.batch.scan.DeprecatedJsonReport; | |||
import org.sonar.batch.scan.report.DeprecatedJsonReport; | |||
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; | |||
import org.sonar.batch.scan.maven.MavenPluginExecutor; | |||
@@ -17,7 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan; | |||
package org.sonar.batch.scan.report; | |||
import com.google.common.collect.ImmutableSet; | |||
import org.junit.Before; | |||
@@ -35,6 +35,7 @@ import org.sonar.api.scan.filesystem.ModuleFileSystem; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.batch.index.DefaultIndex; | |||
import org.sonar.batch.issue.IssueCache; | |||
import org.sonar.batch.scan.report.DeprecatedJsonReport; | |||
import org.sonar.core.i18n.RuleI18nManager; | |||
import org.sonar.java.api.JavaClass; | |||
@@ -48,6 +49,7 @@ import static org.fest.assertions.Assertions.assertThat; | |||
import static org.mockito.Mockito.*; | |||
public class DeprecatedJsonReportTest { | |||
DeprecatedJsonReport deprecatedJsonReport; | |||
DefaultIndex sonarIndex = mock(DefaultIndex.class); | |||
Resource resource = JavaClass.create("KEY"); |
@@ -17,7 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan; | |||
package org.sonar.batch.scan.report; | |||
import com.google.common.collect.Lists; | |||
import org.json.JSONException; | |||
@@ -70,7 +70,7 @@ public class JsonReportTest { | |||
settings = new Settings(); | |||
settings.setProperty(CoreProperties.DRY_RUN, true); | |||
jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache, mock(EventBus.class)); | |||
jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache, mock(EventBus.class), new DefaultComponentSelector()); | |||
} | |||
@Test | |||
@@ -96,7 +96,7 @@ public class JsonReportTest { | |||
StringWriter writer = new StringWriter(); | |||
jsonReport.writeJson(writer); | |||
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/JsonReportTest/report.json"), | |||
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/report/JsonReportTest/report.json"), | |||
writer.toString(), false); | |||
} | |||
@@ -118,7 +118,7 @@ public class JsonReportTest { | |||
StringWriter writer = new StringWriter(); | |||
jsonReport.writeJson(writer); | |||
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/JsonReportTest/report-without-resolved-issues.json"), | |||
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/report/JsonReportTest/report-without-resolved-issues.json"), | |||
writer.toString(), false); | |||
} | |||
@@ -30,18 +30,18 @@ public interface InputFile extends Serializable { | |||
* Canonical path of source directory. | |||
* Example: <code>/path/to/module/src/main/java</code> or <code>C:\path\to\module\src\main\java</code> | |||
*/ | |||
String ATTRIBUTE_SOURCEDIR_PATH = "srcDirPath"; | |||
String ATTRIBUTE_SOURCEDIR_PATH = "SRC_DIR_PATH"; | |||
/** | |||
* Relative path from source directory. File separator is the forward slash ('/'), | |||
* even on MSWindows. | |||
*/ | |||
String ATTRIBUTE_SOURCE_RELATIVE_PATH = "srcRelPath"; | |||
String ATTRIBUTE_SOURCE_RELATIVE_PATH = "SRC_REL_PATH"; | |||
/** | |||
* Detected language | |||
*/ | |||
String ATTRIBUTE_LANGUAGE = "lang"; | |||
String ATTRIBUTE_LANGUAGE = "LANG"; | |||
/** | |||
* |
@@ -35,6 +35,11 @@ import java.util.Map; | |||
*/ | |||
public class DefaultInputFile implements InputFile { | |||
/** | |||
* We're not sure that this is the correct way, so not in API yet. | |||
*/ | |||
public static String ATTRIBUTE_COMPONENT_KEY = "CMP_KEY"; | |||
private final String absolutePath; | |||
private final String path; | |||
private final Map<String, String> attributes; |