summaryrefslogtreecommitdiff
path: root/jps
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2013-01-08 11:11:20 -0800
committerJean-Baptiste Queru <jbq@google.com>2013-01-08 11:11:20 -0800
commitb56ea2a18f232d79481e778085fd64e8ae486fc3 (patch)
tree44e1f6eb4864a45033f865b74fe783e3d784dd6a /jps
downloadidea-b56ea2a18f232d79481e778085fd64e8ae486fc3.tar.gz
Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
Diffstat (limited to 'jps')
-rw-r--r--jps/antLayout/antlayout.iml13
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/antlib.xml11
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/datatypes/Container.java137
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/datatypes/Content.java33
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java56
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/ExtractedDirContent.java82
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/FileSetContainer.java49
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java38
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleBase.java86
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleTests.java42
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java65
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/RenamedFileContainer.java70
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java68
-rw-r--r--jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java98
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java121
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java35
-rwxr-xr-xjps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java25
-rw-r--r--jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java96
-rw-r--r--jps/jps-builders/jps-builders.iml41
-rw-r--r--jps/jps-builders/proto/cmdline_remote_proto.proto164
-rw-r--r--jps/jps-builders/proto/gen_proto.bat2
-rwxr-xr-xjps/jps-builders/proto/gen_proto.sh2
-rw-r--r--jps/jps-builders/proto/javac_remote_proto.proto112
-rw-r--r--jps/jps-builders/src/META-INF/MANIFEST.MF3
-rw-r--r--jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider1
-rw-r--r--jps/jps-builders/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService2
-rw-r--r--jps/jps-builders/src/defaultLogConfig.xml26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java77
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java227
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java97
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/BuildType.java24
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/CanceledStatus.java31
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java266
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/CmdlineRemoteProto.java9578
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/RequestFuture.java57
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java44
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java27
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java53
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java66
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java71
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetIndex.java38
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetLoader.java27
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetRegistry.java39
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java52
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java35
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/FileProcessor.java30
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java62
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/TargetOutputIndex.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/ArtifactBuildTaskProvider.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/impl/ArtifactOutToSourceStorageProvider.java39
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java54
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java75
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java73
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java276
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetChunk.java40
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java183
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java74
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/TargetOutputIndexImpl.java70
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java73
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java35
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java57
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/ExcludedJavaSourceRootProvider.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java294
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java85
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java113
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java107
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java85
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java66
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java506
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java587
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/CollectionFactory.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java136
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java144
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java42
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java78
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMaplet.java65
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMultiMaplet.java98
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java164
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java288
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMaplet.java71
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMultiMaplet.java149
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMaplet.java66
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java98
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java153
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java263
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMaplet.java71
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java143
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Logger.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java2401
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java240
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java108
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java263
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectTransientMultiMaplet.java145
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/OrderProvider.java67
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java143
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java204
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java297
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Streamable.java30
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java330
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java746
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java36
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java33
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java49
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/storage/StorageProvider.java30
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java126
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/client/ProtobufResponseHandler.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java184
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java29
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java260
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java220
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java623
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java211
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoader.java25
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoaderImpl.java76
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/ProfilingHelper.java71
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java163
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BinaryContent.java87
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuildListener.java36
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java216
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuildTask.java24
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java35
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderCategory.java31
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java103
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java41
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ChunkBuildOutputConsumerImpl.java102
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java62
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java183
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java33
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java82
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java99
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java137
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ExternalProcessUtil.java134
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/FSCache.java60
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java226
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java1116
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java74
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java55
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/LineOutputWriter.java215
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/MessageHandler.java31
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java186
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java80
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuildException.java46
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/RebuildRequestedException.java32
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java165
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java139
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java42
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java147
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java148
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTargetType.java74
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java40
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java79
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java280
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JarPathUtil.java35
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java37
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java30
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java47
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java332
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java196
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/DependentJarsEvaluator.java50
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java401
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactPathUtil.java52
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java58
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java67
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java41
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java138
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilder.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java58
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java85
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java121
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootProcessor.java25
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/CopyToDirectoryInstructionCreator.java57
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/DestinationInfo.java41
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ExplodedDestinationInfo.java30
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java84
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java124
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarDestinationInfo.java53
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarInfo.java56
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/PackIntoArchiveInstructionCreator.java71
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SkipAllInstructionCreator.java49
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java35
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java223
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java185
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java214
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java90
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java144
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java93
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/RmiStubsGenerator.java372
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/AnnotationsExcludedJavaSourceRootProvider.java49
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/ClassPostProcessor.java27
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/CopyResourcesUtil.java102
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java36
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/FormsParsing.java245
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java890
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java134
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildMessage.java46
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java119
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CustomBuilderMessage.java44
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/DoneSomethingNotification.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileDeletedEvent.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java50
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/messages/ProgressMessage.java41
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java192
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/resources/StandardResourceBuilderEnabler.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/AbstractStateStorage.java148
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java333
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java153
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java123
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java138
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/CompositeStorageOwner.java70
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java49
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ModuleOutputRootsLayout.java54
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java110
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ProjectTimestamps.java65
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java92
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/StorageOwner.java27
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java135
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampValidityState.java65
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/Timestamps.java37
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ValidityState.java40
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/indices/IgnoredFileIndex.java23
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/indices/ModuleExcludeIndex.java32
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java74
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/indices/impl/ModuleExcludeIndexImpl.java134
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/CompilationCanceledException.java31
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/DummyJavaFileObject.java87
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java217
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java256
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java258
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java219
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java6126
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java281
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java186
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java64
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java219
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java540
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java373
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileConsumer.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileObject.java143
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/PlainMessageDiagnostic.java70
-rw-r--r--jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/a.txt0
-rw-r--r--jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/artifactIncludesArchiveArtifact.ipr24
-rw-r--r--jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.iml12
-rw-r--r--jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.ipr31
-rw-r--r--jps/jps-builders/testData/output/artifactWithoutOutput/data.txt0
-rw-r--r--jps/jps-builders/testData/output/extractDirTest/extractDirTest.ipr37
-rw-r--r--jps/jps-builders/testData/output/extractDirTest/lib/a.jarbin0 -> 332 bytes
-rw-r--r--jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.iml12
-rw-r--r--jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.ipr210
-rw-r--r--jps/jps-builders/testData/output/javacFileEncoding/src/MyClass.java11
-rw-r--r--jps/jps-builders/testData/output/manifestInArtifact/META-INF/MANIFEST.MF3
-rw-r--r--jps/jps-builders/testData/output/manifestInArtifact/manifest.ipr21
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/main/lib/service.jar0
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/main/main.iml23
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/moduleClasspath.ipr14
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/test-util/lib/provided.jar0
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/test-util/lib/runtime.jar0
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/test-util/lib/test.jar0
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/test-util/test-util.iml39
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/util/lib/exported.jar0
-rw-r--r--jps/jps-builders/testData/output/moduleClasspath/util/util.iml21
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/module1/module1.iml13
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/module1/src/Bar1.java3
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/module2/module2.iml13
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/module2/src/Bar2.java3
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/moduleCycle.iml14
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/moduleCycle.ipr14
-rw-r--r--jps/jps-builders/testData/output/moduleCycle/src/Foo.java4
-rw-r--r--jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.iml13
-rw-r--r--jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.ipr20
-rw-r--r--jps/jps-builders/testData/output/moduleTestOutput/src/MyClass.java9
-rw-r--r--jps/jps-builders/testData/output/moduleTestOutput/testSrc/MyTest.java9
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/inner.iml12
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.iml13
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.ipr310
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/b.properties0
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/Class2.java11
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/a.properties0
-rw-r--r--jps/jps-builders/testData/output/overlappingSourceRoots/src/x/MyClass.java6
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/data/d1/x.txt1
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/data/d2/x.txt1
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/data/dir/a/f.txt1
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/data/f.txt1
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/dep/dep.iml12
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/dep/src/a.xml1
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/overwriteTest.iml12
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/overwriteTest.ipr60
-rw-r--r--jps/jps-builders/testData/output/overwriteTest/src/a.xml1
-rw-r--r--jps/jps-builders/testData/output/pathVariables/external/file.txt1
-rw-r--r--jps/jps-builders/testData/output/pathVariables/pathVariables.ipr17
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/resourceCopying.iml12
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/resourceCopying.ipr185
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/a.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/ab.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/copy/file.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/copy/subdir/file2.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/abc.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/xxx.xml0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/copyTree/xyz.txt0
-rw-r--r--jps/jps-builders/testData/output/resourceCopying/src/index.html0
-rw-r--r--jps/jps-builders/testData/output/sourceFolderUnderOutput/a.txt0
-rw-r--r--jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.iml12
-rw-r--r--jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.ipr20
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/AnnotationTest.java111
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/ClassModifierTest.java54
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/ClassPropertyTest.java66
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/ClassRenameTest.java34
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java104
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/FieldModifierTest.java50
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/FieldPropertyTest.java105
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java156
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/ImportTest.java37
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java271
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/LogParser.java96
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java55
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java198
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/MethodModifierTest.java63
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java46
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/PackageInfoTest.java38
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/StorageDumper.java151
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java72
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java98
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy33
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java347
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy105
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/TestProjectBuilderLogger.java86
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/java/ForcedCompilationTest.java39
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy174
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy97
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy74
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java56
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java196
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java411
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java152
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/CleanArtifactOutputOnRebuildTest.java118
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java316
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java113
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java104
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/indices/ModuleExcludeIndexTest.java93
-rw-r--r--jps/lib/gant-1.9.5_groovy-1.7.10.jarbin0 -> 337121 bytes
-rw-r--r--jps/lib/optimizedFileManager.jarbin0 -> 19850 bytes
-rw-r--r--jps/model-api/jps-model-api.iml14
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsCompositeElement.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsDummyElement.java22
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElement.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementChildRole.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementCollection.java39
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementContainer.java44
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementCreator.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementFactory.java70
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementParameterizedCreator.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementReference.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementType.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsElementTypeWithDefaultProperties.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsEncodingConfigurationService.java46
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsEncodingProjectConfiguration.java36
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsEventDispatcher.java38
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsFileTypesConfiguration.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsGlobal.java44
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsModel.java36
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsNamedElement.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsProject.java73
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsReferenceableElement.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsSimpleElement.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsTypedElement.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsUrlList.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/JpsUrlListChangeListener.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java55
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java31
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java47
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java22
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java30
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java31
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java62
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/artifact/elements/ex/JpsComplexPackagingElementBase.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsCompositeElementBase.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementBase.java81
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementChildRoleBase.java39
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementCollectionRole.java55
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementContainerEx.java31
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementReferenceBase.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java42
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedCompositeElementBase.java60
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/ExplodedDirectoryModuleExtension.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootProperties.java38
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootType.java39
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaClasspathKind.java40
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java46
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesRootsEnumerator.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyExtension.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyScope.java40
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java118
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaLibraryType.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleExtension.java48
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleType.java35
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaProjectExtension.java31
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkType.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkTypeWrapper.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/LanguageLevel.java23
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/EclipseCompilerOptions.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JavaCompilers.java23
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JikesCompilerOptions.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsCompilerExcludes.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java77
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerOptions.java41
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java72
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/RmicCompilerOptions.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationProperties.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationState.java23
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationType.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java61
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryCollection.java51
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryListener.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryReference.java34
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRoot.java38
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRootListener.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/JpsTypedLibrary.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdk.java43
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkType.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java39
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesList.java50
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesRootsEnumerator.java28
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java27
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsFacet.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetListener.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetReference.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetType.java26
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsLibraryDependency.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java101
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleContentRootsListener.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleDependency.java30
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleExcludeRootsListener.java24
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleListener.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleReference.java31
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceDependency.java22
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java45
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootListener.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkDependency.java38
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkReferencesTable.java35
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModule.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModuleSourceRoot.java33
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfiguration.java29
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfigurationType.java25
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsTypedRunConfiguration.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java39
-rw-r--r--jps/model-api/src/org/jetbrains/jps/service/SharedThreadPool.java30
-rw-r--r--jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java90
-rw-r--r--jps/model-impl/jps-model-impl.iml16
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsElementFactory1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsEncodingConfigurationService1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.ex.JpsExElementFactory1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JdkVersionDetector1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JpsJavaExtensionService1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.JpsServiceManager1
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.SharedThreadPool1
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java120
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java54
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java32
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java77
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java55
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java73
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java37
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java58
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java45
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java54
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java58
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java49
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java57
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java78
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java59
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java120
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/ex/JpsElementContainerImpl.java137
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsDummyElementImpl.java35
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java151
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java116
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingConfigurationServiceImpl.java75
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingProjectConfigurationImpl.java120
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEventDispatcherBase.java55
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java46
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsFileTypesConfigurationImpl.java62
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalElementReference.java46
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalImpl.java84
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsModelImpl.java75
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java80
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java52
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectElementReference.java46
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectImpl.java152
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsRootElementBase.java58
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsSimpleElementImpl.java60
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListImpl.java69
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListRole.java36
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/impl/runConfiguration/JpsRunConfigurationImpl.java58
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/ExplodedDirectoryModuleExtensionImpl.java92
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaModuleExtensionRole.java38
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaProjectExtensionRole.java38
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java108
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java178
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumerationHandler.java77
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java161
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesRootsEnumeratorImpl.java88
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionImpl.java79
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionRole.java39
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java205
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaModuleExtensionImpl.java138
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaProjectExtensionImpl.java72
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java48
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java48
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java81
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsCompilerExcludesImpl.java73
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java194
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java262
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/runConfiguration/JpsApplicationRunConfigurationPropertiesImpl.java54
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryCollectionImpl.java93
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java184
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryReferenceImpl.java60
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java45
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootImpl.java75
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootRole.java58
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java68
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/library/impl/sdk/JpsSdkImpl.java110
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java191
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesListImpl.java104
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesRootsEnumeratorBase.java100
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java47
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetImpl.java88
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetReferenceImpl.java41
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetRole.java45
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsLibraryDependencyImpl.java62
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleDependencyImpl.java70
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleImpl.java225
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleReferenceImpl.java55
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java46
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceDependencyImpl.java44
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java98
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootRole.java45
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java75
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferenceRole.java41
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferencesTableImpl.java75
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java66
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/service/impl/SharedThreadPoolImpl.java49
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java261
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsFacetTest.java40
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaExtensionTest.java56
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaModelTestCase.java47
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsLibraryTest.java69
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModelTestCase.java35
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleRootModificationUtil.java61
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleTest.java139
-rw-r--r--jps/model-impl/testSrc/org/jetbrains/jps/model/TestJpsEventDispatcher.java85
-rw-r--r--jps/model-serialization/jps-model-serialization.iml18
-rw-r--r--jps/model-serialization/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension2
-rw-r--r--jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java43
-rw-r--r--jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java101
-rw-r--r--jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java93
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JDomSerializationUtil.java82
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementExtensionSerializerBase.java52
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementPropertiesSerializer.java37
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsEncodingModelSerializerExtension.java92
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalExtensionSerializer.java29
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java126
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java83
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsMacroExpander.java73
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializationDataService.java54
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java135
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectExtensionSerializer.java35
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java331
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectSerializationDataExtension.java29
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java51
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java41
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java47
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java95
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactDummyPropertiesSerializer.java40
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactExtensionSerializer.java47
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactPropertiesSerializer.java35
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactSerializer.java398
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementSerializer.java44
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetManagerState.java40
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetState.java74
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetConfigurationSerializer.java70
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java96
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsModuleSerializationDataExtensionImpl.java53
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsProjectSerializationDataExtensionImpl.java52
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsApplicationRunConfigurationSerializer.java47
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java283
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java162
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsEclipseCompilerOptionsSerializer.java57
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java111
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerOptionsSerializer.java57
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerWorkspaceConfigurationSerializer.java48
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/RmicCompilerOptionsSerializer.java54
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryPropertiesSerializer.java35
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryRootTypeSerializer.java51
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryTableSerializer.java266
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkPropertiesSerializer.java38
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java258
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleClasspathSerializer.java46
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModulePropertiesSerializer.java44
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java254
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSerializationDataExtension.java29
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationPropertiesSerializer.java35
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationSerializer.java61
-rw-r--r--jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iml12
-rw-r--r--jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.ipr55
-rw-r--r--jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iws8
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/.idea/compiler.xml43
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/.idea/encodings.xml5
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/.idea/misc.xml7
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/.idea/modules.xml9
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/.idea/workspace.xml8
-rw-r--r--jps/model-serialization/testData/compilerConfigurationDir/compilerConfiguration.iml12
-rw-r--r--jps/model-serialization/testData/config/options/applicationLibraries.xml14
-rw-r--r--jps/model-serialization/testData/config/options/encoding.xml5
-rw-r--r--jps/model-serialization/testData/config/options/filetypes.xml15
-rw-r--r--jps/model-serialization/testData/config/options/jdk.table.xml72
-rw-r--r--jps/model-serialization/testData/fileEncoding/dir/with-encoding.xml2
-rw-r--r--jps/model-serialization/testData/fileEncoding/dir/without-encoding.xml1
-rw-r--r--jps/model-serialization/testData/fileEncoding/fileEncoding.ipr15
-rw-r--r--jps/model-serialization/testData/imlUnderDotIdea/.idea/imlUnderDotIdea.iml12
-rw-r--r--jps/model-serialization/testData/imlUnderDotIdea/.idea/misc.xml7
-rw-r--r--jps/model-serialization/testData/imlUnderDotIdea/.idea/modules.xml9
-rw-r--r--jps/model-serialization/testData/projectSdkWithoutType/projectSdkWithoutType.ipr9
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/.idea/misc.xml7
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/.idea/modules.xml9
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/shared.xml17
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/test.xml23
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/.idea/workspace.xml182
-rw-r--r--jps/model-serialization/testData/run-configurations-dir/run-configurations.iml12
-rw-r--r--jps/model-serialization/testData/run-configurations/run-configurations.iml12
-rw-r--r--jps/model-serialization/testData/run-configurations/run-configurations.ipr50
-rw-r--r--jps/model-serialization/testData/run-configurations/run-configurations.iws169
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/.name1
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/artifacts/dir.xml17
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/artifacts/jar.xml10
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/compiler.xml21
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/encodings.xml8
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/libraries/jarDir.xml13
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/libraries/junit.xml15
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/libraries/log4j.xml11
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/misc.xml7
-rw-r--r--jps/model-serialization/testData/sampleProject/.idea/modules.xml11
-rw-r--r--jps/model-serialization/testData/sampleProject/main.iml16
-rw-r--r--jps/model-serialization/testData/sampleProject/util/util.iml41
-rw-r--r--jps/model-serialization/testData/sampleProject/xxx/xxx.iml14
-rw-r--r--jps/model-serialization/testSrc/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension1
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/JpsEncodingConfigurationServiceTest.java39
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsArtifactSerializationTest.java72
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsCompilerConfigurationTest.java67
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsGlobalSerializationTest.java65
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java181
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsRunConfigurationsSerializationTest.java51
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsSerializationTestCase.java90
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsTestSerializerExtension.java34
-rw-r--r--jps/standalone-builder/jps-standalone-builder.iml27
-rw-r--r--jps/standalone-builder/src/jps.gdsl31
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/LayoutInfo.java31
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/build/GroovyModelInitializer.java50
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java178
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/BuildInfoPrinter.java30
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java39
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java265
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy131
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/LayoutInfo.java22
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/gant/TeamCityBuildInfoPrinter.java76
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy34
692 files changed, 71165 insertions, 0 deletions
diff --git a/jps/antLayout/antlayout.iml b/jps/antLayout/antlayout.iml
new file mode 100644
index 000000000000..8c643bed5d30
--- /dev/null
+++ b/jps/antLayout/antlayout.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Ant" level="project" />
+ </component>
+</module>
+
diff --git a/jps/antLayout/src/jetbrains/antlayout/antlib.xml b/jps/antLayout/src/jetbrains/antlayout/antlib.xml
new file mode 100755
index 000000000000..bc7053c450e8
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/antlib.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<antlib>
+ <taskdef name="layout" classname="jetbrains.antlayout.tasks.LayoutTask"/>
+ <typedef name="jar" classname="jetbrains.antlayout.datatypes.JarContainer"/>
+ <typedef name="zip" classname="jetbrains.antlayout.datatypes.ZipContainer"/>
+ <typedef name="dir" classname="jetbrains.antlayout.datatypes.DirContainer"/>
+ <typedef name="renamedFile" classname="jetbrains.antlayout.datatypes.RenamedFileContainer"/>
+ <typedef name="extractedDir" classname="jetbrains.antlayout.datatypes.ExtractedDirContent"/>
+ <typedef name="module" classname="jetbrains.antlayout.datatypes.IdeaModule"/>
+ <typedef name="moduleTests" classname="jetbrains.antlayout.datatypes.IdeaModuleTests"/>
+</antlib> \ No newline at end of file
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java
new file mode 100755
index 000000000000..3cb492895c60
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import jetbrains.antlayout.util.TempFileFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.ZipFileSet;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author max
+ */
+public abstract class Container extends Content {
+ private List<Content> children = new ArrayList<Content>();
+
+ private String excludes = null;
+ private String includes = null;
+
+ public void addFileset(FileSet set) {
+ children.add(new FileSetContainer(set));
+ }
+
+ public void addZipfileset(ZipFileSet set) {
+ children.add(new FileSetContainer(set));
+ }
+
+ public void addDir(DirContainer container) {
+ children.add(container);
+ }
+
+ public void addJar(JarContainer container) {
+ children.add(container);
+ }
+
+ public void addZip(ZipContainer container) {
+ children.add(container);
+ }
+
+ public void addRenamedFile(RenamedFileContainer container) {
+ children.add(container);
+ }
+
+ public void addExtractedDir(ExtractedDirContent content) {
+ children.add(content);
+ }
+
+ public void addContainer(Container container) {
+ children.add(container);
+ }
+
+ public void addContent(Content content) {
+ children.add(content);
+ }
+
+ public void addModule(IdeaModule module) {
+ children.add(new FileSetContainer(module));
+ }
+
+ public void addModuleTests(IdeaModuleTests module) {
+ children.add(new FileSetContainer(module));
+ }
+
+ public List<Content> getChildren() {
+ return children;
+ }
+
+
+ public void setExcludes(String excludes) {
+ this.excludes = excludes;
+ }
+
+ public void setIncludes(String includes) {
+ this.includes = includes;
+ }
+
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ Set<LayoutFileSet> result = new LinkedHashSet<LayoutFileSet>();
+
+ for (Content child : children) {
+ for (LayoutFileSet set : child.build(temp)) {
+ result.add(createCopy(set));
+ }
+ }
+
+ ArrayList<LayoutFileSet> list = new ArrayList<LayoutFileSet>(result);
+ for (LayoutFileSet set : list) {
+ if (includes != null) {
+ set.setIncludes(includes);
+ }
+
+ if (excludes != null) {
+ set.setExcludes(excludes);
+ }
+ }
+
+ return list;
+ }
+
+ protected static LayoutFileSet createCopy(FileSet set) {
+ if (set instanceof IdeaModule) {
+ return new IdeaModule((IdeaModule) set);
+ }
+ if (set instanceof IdeaModuleTests) {
+ return new IdeaModuleTests((IdeaModuleTests) set);
+ }
+ if (set instanceof ZipFileSet) {
+ return new LayoutFileSet((ZipFileSet) set.clone());
+ } else {
+ return new LayoutFileSet((FileSet) set.clone());
+ }
+ }
+
+ public void validateArguments() throws BuildException {
+ for (Content child : children) {
+ child.validateArguments();
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java
new file mode 100755
index 000000000000..2d7bf76ae0cd
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.types.DataType;
+import org.apache.tools.ant.BuildException;
+
+import java.util.List;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+/**
+ * @author max
+ */
+public abstract class Content extends DataType {
+ public abstract List<LayoutFileSet> build(TempFileFactory temp);
+
+ public abstract void validateArguments() throws BuildException;
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java
new file mode 100755
index 000000000000..b20ff004b620
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * @author max
+ */
+public class DirContainer extends Container {
+ private String dirName;
+
+ public void setName(String name) {
+ dirName = name;
+ }
+
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ List<LayoutFileSet> unprefixed = super.build(temp);
+ List<LayoutFileSet> prefixed = new ArrayList<LayoutFileSet>();
+
+ for (LayoutFileSet set : unprefixed) {
+ LayoutFileSet copy = createCopy(set);
+ copy.setPrefix(dirName + "/" + set.getPrefix(getProject()));
+ prefixed.add(copy);
+ }
+
+ return prefixed;
+ }
+
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+ if (dirName == null) {
+ throw new BuildException("dirname attribute must be specified for direntry");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/ExtractedDirContent.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/ExtractedDirContent.java
new file mode 100644
index 000000000000..6a545ade30a0
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/ExtractedDirContent.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import jetbrains.antlayout.util.TempFileFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Expand;
+import org.apache.tools.ant.types.PatternSet;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class ExtractedDirContent extends Content {
+ private String jarPath;
+ private String pathInJar = "";
+ private Expand expandTask;
+
+ public ExtractedDirContent() {
+ expandTask = new Expand();
+ expandTask.setTaskName("unzip");
+ }
+
+ public void setJarPath(String jarPath) {
+ this.jarPath = jarPath;
+ }
+
+ public void setPathInJar(String pathInJar) {
+ this.pathInJar = pathInJar;
+ }
+
+ @Override
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ final File outputDir = temp.allocateTempFile("extractedDir");
+ expandTask.setProject(getProject());
+ expandTask.setSrc(new File(jarPath.replace('/', File.separatorChar)));
+
+ File target = outputDir;
+ if (!pathInJar.endsWith("/")) {
+ pathInJar += "/";
+ }
+ if (pathInJar.startsWith("/")) {
+ pathInJar = pathInJar.substring(1);
+ }
+ if (pathInJar.length() > 0) {
+ final PatternSet patternSet = new PatternSet();
+ patternSet.createInclude().setName(pathInJar + "**");
+ expandTask.addPatternset(patternSet);
+ target = new File(outputDir, pathInJar.replace('/', File.separatorChar));
+ }
+ expandTask.setDest(outputDir);
+ expandTask.perform();
+
+ final LayoutFileSet fileSet = new LayoutFileSet();
+ fileSet.setDir(target);
+ return Collections.singletonList(fileSet);
+ }
+
+ @Override
+ public void validateArguments() throws BuildException {
+ if (jarPath == null) {
+ throw new BuildException("jarPath attribute must be specified for extractedDir tag");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/FileSetContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/FileSetContainer.java
new file mode 100644
index 000000000000..af5c17fae9ec
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/FileSetContainer.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import jetbrains.antlayout.util.TempFileFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.FileSet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class FileSetContainer extends Content {
+ private FileSet fileSet;
+
+ public FileSetContainer(FileSet fileSet) {
+ this.fileSet = fileSet;
+ }
+
+ @Override
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ return Collections.singletonList(Container.createCopy(fileSet));
+ }
+
+ @Override
+ public void validateArguments() throws BuildException {
+ if (fileSet instanceof IdeaModuleBase) {
+ ((IdeaModuleBase) fileSet).validateArguments();
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java
new file mode 100755
index 000000000000..f60aec635998
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class IdeaModule extends IdeaModuleBase {
+ public IdeaModule() {
+ }
+
+ public IdeaModule(IdeaModule fileset) {
+ super(fileset);
+ }
+
+ protected String getKind() {
+ return "production";
+ }
+
+ protected String getOutputDirProperty() {
+ return "module." + getName() + ".output.main";
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleBase.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleBase.java
new file mode 100644
index 000000000000..c9d8c564338f
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleBase.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.ZipFileSet;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public abstract class IdeaModuleBase extends LayoutFileSet {
+ private String name;
+
+ protected IdeaModuleBase() {
+ setExcludes("classpath.index");
+ }
+
+ public IdeaModuleBase(ZipFileSet fileset) {
+ super(fileset);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ setDir(getOutputDir());
+ }
+
+ protected File getOutputDir() {
+ String common = getProject().getProperty("modules.output");
+ if (common != null) {
+ return new File(new File(common), getKind() + "/" + getName());
+ }
+
+ String adhoc = getProject().getProperty(getOutputDirProperty());
+ return adhoc != null ? new File(adhoc) : null;
+ }
+
+ public void validateArguments() throws BuildException {
+ if (name == null) {
+ throw new BuildException("name attribute must be specified for module entry");
+ }
+
+ File outputDir = getOutputDir();
+
+ if (outputDir == null || !outputDir.exists()) {
+ throw new BuildException("No " + getKind() + " output found for module " + name +
+ ". Either modules.output property references project output that doesn't contain this module or " +
+ getOutputDirProperty() + " is not defined or references non-existing directory.");
+ }
+ }
+
+ protected abstract String getOutputDirProperty();
+
+ protected abstract String getKind();
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ IdeaModule that = (IdeaModule) o;
+ return getDir(getProject()).equals(that.getDir(getProject()));
+ }
+
+ public int hashCode() {
+ return getDir(getProject()).hashCode();
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleTests.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleTests.java
new file mode 100644
index 000000000000..a8be4dfbd5f6
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModuleTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.types.ZipFileSet;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class IdeaModuleTests extends IdeaModuleBase {
+ public IdeaModuleTests() {
+ }
+
+ public IdeaModuleTests(ZipFileSet fileset) {
+ super(fileset);
+ }
+
+ @Override
+ protected String getOutputDirProperty() {
+ return "module." + getName() + ".output.test";
+ }
+
+ @Override
+ protected String getKind() {
+ return "test";
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java
new file mode 100644
index 000000000000..e641f4fd1b9a
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.Main;
+import org.apache.tools.ant.taskdefs.*;
+import org.apache.tools.ant.types.ZipFileSet;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class JarContainer extends ZipContainer {
+ protected Zip createTask() {
+ String version = Main.getAntVersion();
+ Jar task;
+ if (version != null && (version.indexOf("1.8.0") != -1 || version.indexOf("1.8.1") != -1)) {
+ task = new PatchedJar();
+ }
+ else {
+ task = new Jar();
+ }
+ task.setTaskName("jar");
+ task.setWhenmanifestonly((Zip.WhenEmpty) Zip.WhenEmpty.getInstance(Zip.WhenEmpty.class, "skip"));
+ return task;
+ }
+
+ public void setIndex(boolean flag) {
+ ((Jar) task).setIndex(flag);
+ }
+
+ public void setManifestEncoding(String manifestEncoding) {
+ ((Jar) task).setManifestEncoding(manifestEncoding);
+ }
+
+ public void setManifest(File manifestFile) {
+ ((Jar) task).setManifest(manifestFile);
+ }
+
+ public void setFilesetmanifest(Jar.FilesetManifestConfig config) {
+ ((Jar) task).setFilesetmanifest(config);
+ }
+
+ public void addConfiguredManifest(Manifest newManifest) throws ManifestException {
+ ((Jar) task).addConfiguredManifest(newManifest);
+ }
+
+ public void addMetainf(ZipFileSet fs) {
+ ((Jar) task).addMetainf(fs);
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/RenamedFileContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/RenamedFileContainer.java
new file mode 100644
index 000000000000..c1011763fe44
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/RenamedFileContainer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import jetbrains.antlayout.util.TempFileFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Copy;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class RenamedFileContainer extends Container {
+ private String filePath;
+ private String newName;
+ private Copy copyTask;
+
+ public RenamedFileContainer() {
+ copyTask = new Copy();
+ copyTask.setTaskName("copy");
+ }
+
+ public void setFilePath(String filePath) {
+ this.filePath = filePath;
+ }
+
+ public void setNewName(String newName) {
+ this.newName = newName;
+ }
+
+ @Override
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ final LayoutFileSet fileSet = new LayoutFileSet();
+ final File destFile = temp.allocateTempFile(newName);
+ copyTask.setProject(getProject());
+ copyTask.setFile(new File(filePath.replace('/', File.separatorChar)));
+ copyTask.setTofile(destFile);
+ copyTask.perform();
+ fileSet.setFile(destFile);
+ return Collections.singletonList(fileSet);
+ }
+
+ @Override
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+ if (filePath == null) {
+ throw new BuildException("filePath attribute must be specified for renamedFile tag");
+ }
+ if (newName == null) {
+ throw new BuildException("newName attribute must be specified for renamedFile tag");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java
new file mode 100755
index 000000000000..bd125ee6d99d
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+import java.io.File;
+import java.util.List;
+import java.util.Collections;
+
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * @author max
+ */
+public class RootContainer extends Container {
+ private File destDirectory;
+
+ public RootContainer(File destDirectory) {
+ this.destDirectory = destDirectory;
+ }
+
+
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ List<LayoutFileSet> built = super.build(temp);
+ for (LayoutFileSet set : built) {
+ copySet(set);
+ }
+
+ return Collections.emptyList();
+ }
+
+ private void copySet(LayoutFileSet set) {
+ Copy task = new Copy();
+ task.setTaskName("copy");
+ task.setProject(getProject());
+ String prefix = set.getPrefix(getProject());
+ File target = prefix.length() > 0 ? new File(destDirectory, prefix + "/") : destDirectory;
+
+ target.mkdirs();
+
+ task.setTodir(target);
+ LayoutFileSet unprefixed = (LayoutFileSet) set.clone();
+ unprefixed.setPrefix("");
+
+ task.addFileset(unprefixed);
+ task.perform();
+ }
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java
new file mode 100644
index 000000000000..5c47da8f88b7
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+import org.apache.tools.ant.taskdefs.Zip;
+import org.apache.tools.ant.BuildException;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author max
+ */
+public class ZipContainer extends Container {
+ private String name;
+ protected Zip task;
+
+ public ZipContainer() {
+ task = createTask();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<LayoutFileSet> build(TempFileFactory temp) {
+ List<LayoutFileSet> built = super.build(temp);
+ File dest = temp.allocateTempFile(name);
+
+ task.setProject(getProject());
+ task.setDestFile(dest);
+
+ for (LayoutFileSet set : built) {
+ task.addZipfileset(set);
+ }
+
+ LayoutFileSet result = new LayoutFileSet();
+ result.setFile(dest);
+
+ task.perform();
+
+ return Arrays.asList(result);
+ }
+
+ protected Zip createTask() {
+ Zip task = new Zip();
+ task.setTaskName("zip");
+ return task;
+ }
+
+ public void setCompress(boolean compress) {
+ task.setCompress(compress);
+ }
+
+ public void setFilesonly(boolean f) {
+ task.setFilesonly(f);
+ }
+
+ public void setDuplicate(Zip.Duplicate df) {
+ task.setDuplicate(df);
+ }
+
+ public void setEncoding(String encoding) {
+ task.setEncoding(encoding);
+ }
+
+ public void setBasedir(File baseDir) {
+ task.setBasedir(baseDir);
+ }
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+
+ if (name == null) {
+ throw new BuildException("name attribute must be specified for zipentry or jarentry");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java b/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java
new file mode 100755
index 000000000000..be6586f7e0dc
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.tasks;
+
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import jetbrains.antlayout.datatypes.*;
+import jetbrains.antlayout.util.TempFileFactory;
+import org.apache.tools.ant.types.FileSet;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class LayoutTask extends Task {
+ private List<Content> containers = new ArrayList<Content>();
+ private File destDir;
+
+ public void addDir(DirContainer container) {
+ containers.add(container);
+ }
+
+ public void addJar(JarContainer container) {
+ containers.add(container);
+ }
+
+ public void addZip(ZipContainer container) {
+ containers.add(container);
+ }
+
+ public void addRenamedFile(RenamedFileContainer container) {
+ containers.add(container);
+ }
+
+ public void addExtractedDir(ExtractedDirContent content) {
+ containers.add(content);
+ }
+
+ public void addModule(IdeaModule module) {
+ containers.add(new FileSetContainer(module));
+ }
+
+ public void addModuleTests(IdeaModuleTests module) {
+ containers.add(new FileSetContainer(module));
+ }
+
+ public void addFileset(FileSet fileSet) {
+ containers.add(new FileSetContainer(fileSet));
+ }
+
+ public void setTodir(File dir) {
+ destDir = dir;
+ }
+
+ public File getDestDir() {
+ return destDir;
+ }
+
+ public void execute() throws BuildException {
+ validateArguments();
+
+ RootContainer root = new RootContainer(destDir);
+ root.setProject(getProject());
+ for (Content content : containers) {
+ root.addContent(content);
+ }
+
+ final File tempDir = new File(destDir, "___tmp___");
+ tempDir.mkdirs();
+
+ root.build(new TempFileFactory() {
+ int counter = 0;
+ public File allocateTempFile(String name) {
+ File localTmp = new File(tempDir, "_" + counter + "/");
+ counter++;
+ localTmp.mkdirs();
+ return new File(localTmp, name);
+ }
+ });
+
+ deleteRecursively(tempDir);
+ }
+
+ protected void deleteRecursively(File d) {
+ if (d.isDirectory()) {
+ for (File file : d.listFiles()) {
+ deleteRecursively(file);
+ }
+ }
+
+ if (!d.delete()) {
+ throw new BuildException("Unable to delete file " + d.getAbsolutePath());
+ }
+ }
+
+ private void validateArguments() throws BuildException {
+ if (destDir == null) {
+ throw new BuildException("todir attribute must be specified");
+ }
+
+ for (Content content : containers) {
+ content.validateArguments();
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java b/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java
new file mode 100755
index 000000000000..aeec79422ab3
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.util;
+
+import org.apache.tools.ant.types.ZipFileSet;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * @author max
+ */
+public class LayoutFileSet extends ZipFileSet {
+ public LayoutFileSet() {
+ }
+
+ public LayoutFileSet(FileSet fileset) {
+ super(fileset);
+ }
+
+ public LayoutFileSet(ZipFileSet fileset) {
+ super(fileset);
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java b/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java
new file mode 100755
index 000000000000..3aed9e338e8b
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package jetbrains.antlayout.util;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public interface TempFileFactory {
+ File allocateTempFile(String name);
+}
diff --git a/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java b/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java
new file mode 100644
index 000000000000..511f63bdaded
--- /dev/null
+++ b/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tools.ant.taskdefs;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.ArchiveFileSet;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+
+import java.io.File;
+
+/**
+ * This class is added to workaround https://issues.apache.org/bugzilla/show_bug.cgi?id=49605
+ * in Ant 1.8.0 and 1.8.1
+ *
+ * @author nik
+ */
+public class PatchedJar extends Jar {
+ private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+
+ @Override
+ protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs, File zipFile, boolean needsUpdate) throws BuildException {
+ if (skipWriting) {
+ // this pass is only there to construct the merged
+ // manifest this means we claim an update was needed and
+ // only include the manifests, skipping any uptodate
+ // checks here defering them for the second run
+ Resource[][] manifests = grabManifests(rcs);
+ int count = 0;
+ for (int i = 0; i < manifests.length; i++) {
+ count += manifests[i].length;
+ }
+ log("found a total of " + count + " manifests in "
+ + manifests.length + " resource collections",
+ Project.MSG_VERBOSE);
+ return new ArchiveState(true, manifests);
+ }
+
+ return super.getResourcesToAdd(rcs, zipFile, needsUpdate);
+ }
+
+ /**
+ * This method is copied from Jar class in Ant 1.8.2
+ */
+ private Resource[][] grabManifests(ResourceCollection[] rcs) {
+ Resource[][] manifests = new Resource[rcs.length][];
+ for (int i = 0; i < rcs.length; i++) {
+ Resource[][] resources = null;
+ if (rcs[i] instanceof FileSet) {
+ resources = grabResources(new FileSet[] {(FileSet) rcs[i]});
+ } else {
+ resources = grabNonFileSetResources(new ResourceCollection[] {
+ rcs[i]
+ });
+ }
+ for (int j = 0; j < resources[0].length; j++) {
+ String name = resources[0][j].getName().replace('\\', '/');
+ if (rcs[i] instanceof ArchiveFileSet) {
+ ArchiveFileSet afs = (ArchiveFileSet) rcs[i];
+ if (!"".equals(afs.getFullpath(getProject()))) {
+ name = afs.getFullpath(getProject());
+ } else if (!"".equals(afs.getPrefix(getProject()))) {
+ String prefix = afs.getPrefix(getProject());
+ if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
+ prefix += "/";
+ }
+ name = prefix + name;
+ }
+ }
+ if (name.equalsIgnoreCase(MANIFEST_NAME)) {
+ manifests[i] = new Resource[] {resources[0][j]};
+ break;
+ }
+ }
+ if (manifests[i] == null) {
+ manifests[i] = new Resource[0];
+ }
+ }
+ return manifests;
+ }
+}
diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml
new file mode 100644
index 000000000000..9be26469dcaf
--- /dev/null
+++ b/jps/jps-builders/jps-builders.iml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" exported="" />
+ <orderEntry type="module" module-name="forms_rt" />
+ <orderEntry type="module" module-name="forms-compiler" />
+ <orderEntry type="module" module-name="instrumentation-util" />
+ <orderEntry type="library" exported="" name="asm4" level="project" />
+ <orderEntry type="library" name="JDOM" level="project" />
+ <orderEntry type="library" name="NanoXML" level="project" />
+ <orderEntry type="library" name="jgoodies-forms" level="project" />
+ <orderEntry type="library" name="Netty" level="project" />
+ <orderEntry type="library" exported="" name="protobuf" level="project" />
+ <orderEntry type="module-library" scope="RUNTIME">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/optimizedFileManager.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module" module-name="java-runtime" scope="RUNTIME" />
+ <orderEntry type="library" name="Log4J" level="project" />
+ <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="library" scope="RUNTIME" name="Eclipse" level="project" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="module" module-name="jps-model-serialization" />
+ <orderEntry type="module" module-name="jps-model-impl" />
+ <orderEntry type="library" scope="TEST" name="Groovy" level="project" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/proto/cmdline_remote_proto.proto b/jps/jps-builders/proto/cmdline_remote_proto.proto
new file mode 100644
index 000000000000..4023ca6d823c
--- /dev/null
+++ b/jps/jps-builders/proto/cmdline_remote_proto.proto
@@ -0,0 +1,164 @@
+package org.jetbrains.jpsservice;
+
+option java_package = "org.jetbrains.jps.api";
+option optimize_for = LITE_RUNTIME;
+
+message Message {
+
+ message UUID {
+ required sint64 most_sig_bits = 1;
+ required sint64 least_sig_bits = 2;
+ }
+
+ message KeyValuePair {
+ required string key = 1;
+ required string value = 2;
+ }
+
+ enum Type {
+ CONTROLLER_MESSAGE = 1;
+ BUILDER_MESSAGE = 2;
+ FAILURE = 3;
+ }
+
+ message Failure {
+ optional int32 error_code = 1;
+ optional string description = 2;
+ optional string stacktrace = 3;
+ }
+
+ message ControllerMessage {
+ enum Type {
+ BUILD_PARAMETERS = 1;
+ CANCEL_BUILD_COMMAND = 2;
+ FS_EVENT = 3;
+ CONSTANT_SEARCH_RESULT = 4;
+ }
+
+ message FSEvent {
+ required uint64 ordinal = 1;
+ repeated string changed_paths = 2;
+ repeated string deleted_paths = 3;
+ }
+
+ message GlobalSettings {
+ repeated KeyValuePair path_variable = 1;
+ required string global_options_path = 5;
+ }
+
+ message ParametersMessage {
+ message TargetTypeBuildScope {
+ required string type_id = 1;
+ optional bool all_targets = 2;
+ repeated string target_id = 3;
+ }
+
+ enum Type {
+ REBUILD = 1;
+ MAKE = 2;
+ CLEAN = 3;
+ FORCED_COMPILATION = 4;
+ UP_TO_DATE_CHECK = 5;
+ }
+
+ required Type build_type = 1;
+ optional GlobalSettings global_settings = 2;
+ optional string project_id = 3;
+ repeated TargetTypeBuildScope scope = 4;
+ repeated string file_path = 5;
+ repeated KeyValuePair builder_parameter = 6;
+ }
+
+ message ConstantSearchResult {
+ required string owner_class_name = 1;
+ required string field_name = 2;
+ required bool is_success = 3;
+ repeated string path = 4;
+ }
+
+ required Type type = 1;
+ optional ParametersMessage params_message = 2;
+ optional FSEvent fs_event = 3;
+ optional ConstantSearchResult constant_search_result = 4;
+ }
+
+ message BuilderMessage {
+ enum Type {
+ PARAM_REQUEST = 1;
+ BUILD_EVENT = 2;
+ COMPILE_MESSAGE = 3;
+ CONSTANT_SEARCH_TASK = 4;
+ }
+
+ message BuildEvent {
+ enum Type {
+ BUILD_COMPLETED = 1;
+ FILES_GENERATED = 2;
+ CUSTOM_BUILDER_MESSAGE = 3;
+ }
+
+ enum Status {
+ CANCELED = 1;
+ ERRORS = 2;
+ SUCCESS = 3;
+ UP_TO_DATE = 4;
+ }
+
+ message GeneratedFile {
+ required string output_root = 1;
+ required string relative_path = 2;
+ }
+
+ message CustomBuilderMessage {
+ required string builder_id = 1;
+ required string message_type = 2;
+ required string message_text = 3;
+ }
+
+ required Type event_type = 1;
+ optional string description = 2;
+ optional Status completion_status = 3;
+ repeated GeneratedFile generated_files = 4;
+ optional CustomBuilderMessage custom_builder_message = 5;
+ }
+
+ message CompileMessage {
+ enum Kind {
+ ERROR = 1;
+ WARNING = 2;
+ INFO = 3;
+ PROGRESS = 4;
+ }
+ required Kind kind = 1;
+ optional string text = 2;
+ optional string source_file_path = 3;
+ optional uint64 problem_begin_offset = 4;
+ optional uint64 problem_end_offset = 5;
+ optional uint64 problem_location_offset = 6;
+ optional uint64 line = 7;
+ optional uint64 column = 8;
+ optional float done = 9;
+ }
+
+ message ConstantSearchTask {
+ required string owner_class_name = 1;
+ required string field_name = 2;
+ required int32 access_flags = 3;
+ optional bool is_access_changed = 4 [default = false];
+ optional bool is_field_removed = 5 [default = false];
+ }
+
+ required Type type = 1;
+ optional BuildEvent build_event = 2;
+ optional CompileMessage compile_message = 3;
+ optional ConstantSearchTask constant_search_task = 4;
+ }
+
+ required UUID session_id = 1;
+ required Type type = 2;
+ optional ControllerMessage controller_message = 3;
+ optional BuilderMessage builder_message = 4;
+ optional Failure failure = 5;
+}
+
+
diff --git a/jps/jps-builders/proto/gen_proto.bat b/jps/jps-builders/proto/gen_proto.bat
new file mode 100644
index 000000000000..7d8f0c4d1183
--- /dev/null
+++ b/jps/jps-builders/proto/gen_proto.bat
@@ -0,0 +1,2 @@
+call protoc -I=. --java_out=../src javac_remote_proto.proto
+call protoc -I=. --java_out=../src cmdline_remote_proto.proto \ No newline at end of file
diff --git a/jps/jps-builders/proto/gen_proto.sh b/jps/jps-builders/proto/gen_proto.sh
new file mode 100755
index 000000000000..e0788efa6e2d
--- /dev/null
+++ b/jps/jps-builders/proto/gen_proto.sh
@@ -0,0 +1,2 @@
+protoc -I=. --java_out=../src javac_remote_proto.proto
+protoc -I=. --java_out=../src cmdline_remote_proto.proto \ No newline at end of file
diff --git a/jps/jps-builders/proto/javac_remote_proto.proto b/jps/jps-builders/proto/javac_remote_proto.proto
new file mode 100644
index 000000000000..c9991c036046
--- /dev/null
+++ b/jps/jps-builders/proto/javac_remote_proto.proto
@@ -0,0 +1,112 @@
+package org.jetbrains.javac;
+
+option java_package = "org.jetbrains.jps.javac";
+option optimize_for = LITE_RUNTIME;
+
+message Message {
+
+ message UUID {
+ required sint64 most_sig_bits = 1;
+ required sint64 least_sig_bits = 2;
+ }
+
+ enum Type {
+ REQUEST = 1;
+ RESPONSE = 2;
+ FAILURE = 3;
+ }
+
+ message Failure {
+ optional int32 error_code = 1;
+ optional string description = 2;
+ optional string stacktrace = 3;
+ }
+
+ message Request {
+ enum Type {
+ COMPILE = 1;
+ CANCEL = 2;
+ SHUTDOWN = 3;
+ }
+
+ message OutputGroup {
+ required string output_root = 1;
+ repeated string source_root = 2;
+ }
+
+ required Type request_type = 1;
+ repeated string option = 2;
+ repeated string file = 3;
+ repeated string platform_classpath = 4;
+ repeated string classpath = 5;
+ repeated string sourcepath = 6;
+ repeated OutputGroup output = 7;
+ }
+
+ message Response {
+ enum Type {
+ BUILD_MESSAGE = 1;
+ OUTPUT_OBJECT = 2;
+ CLASS_DATA = 3;
+ BUILD_COMPLETED = 4;
+ REQUEST_ACK = 5;
+ }
+
+ message CompileMessage {
+ enum Kind {
+ ERROR = 1;
+ WARNING = 2;
+ MANDATORY_WARNING = 3;
+ NOTE = 4;
+ OTHER = 5;
+ STD_OUT = 6;
+ }
+ required Kind kind = 1;
+ optional string text = 2;
+ optional string source_uri = 3;
+ optional uint64 problem_begin_offset = 4;
+ optional uint64 problem_end_offset = 5;
+ optional uint64 problem_location_offset = 6;
+ optional uint64 line = 7;
+ optional uint64 column = 8;
+ }
+
+ message OutputObject {
+ enum Kind {
+ SOURCE = 1;
+ CLASS = 2;
+ HTML = 3;
+ OTHER = 4;
+ }
+
+ required Kind kind = 1;
+ required string file_path = 2;
+ optional string output_root = 3;
+ optional string relative_path = 4;
+ optional string class_name = 5;
+ optional string source_uri = 6;
+ optional bytes content = 7;
+ }
+
+ message ClassData {
+ required string class_name = 1;
+ repeated string import_statement = 2;
+ repeated string static_import = 3;
+ repeated string identifier = 4;
+ }
+
+ required Type response_type = 1;
+ optional CompileMessage compile_message = 2;
+ optional OutputObject output_object = 3;
+ optional ClassData class_data = 4;
+ optional bool completion_status = 5;
+ }
+
+ required UUID session_id = 1;
+ required Type message_type = 2;
+ optional Request request = 3;
+ optional Response response = 4;
+ optional Failure failure = 5;
+}
+
+
diff --git a/jps/jps-builders/src/META-INF/MANIFEST.MF b/jps/jps-builders/src/META-INF/MANIFEST.MF
new file mode 100644
index 000000000000..63c029fd45be
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: org.jetbrains.ether.StorageDumper
+
diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider
new file mode 100644
index 000000000000..e398bfd69f5c
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider
@@ -0,0 +1 @@
+org.jetbrains.jps.incremental.java.AnnotationsExcludedJavaSourceRootProvider \ No newline at end of file
diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
new file mode 100644
index 000000000000..59cb6e43434f
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
@@ -0,0 +1,2 @@
+org.jetbrains.jps.incremental.JavaBuilderService
+org.jetbrains.jps.incremental.artifacts.ArtifactBuilderService
diff --git a/jps/jps-builders/src/defaultLogConfig.xml b/jps/jps-builders/src/defaultLogConfig.xml
new file mode 100644
index 000000000000..84ae048d51cb
--- /dev/null
+++ b/jps/jps-builders/src/defaultLogConfig.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.err"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="file" class="org.apache.log4j.RollingFileAppender">
+ <param name="MaxFileSize" value="20Mb"/>
+ <param name="MaxBackupIndex" value="20"/>
+ <param name="file" value="server.log"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d [%7r] %6p - %30.30c - %m \n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value="info" />
+ <appender-ref ref="file" />
+ </root>
+
+</log4j:configuration>
diff --git a/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java b/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
new file mode 100644
index 000000000000..683a8b02abb0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.NotNullFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author max
+ */
+public class ModuleChunk {
+ private static final NotNullFunction<JpsModule,String> GET_NAME = new NotNullFunction<JpsModule, String>() {
+ @NotNull
+ @Override
+ public String fun(JpsModule dom) {
+ return dom.getName();
+ }
+ };
+ private Set<JpsModule> myModules;
+ private final boolean myContainsTests;
+ private Set<ModuleBuildTarget> myTargets;
+
+ public ModuleChunk(Set<ModuleBuildTarget> targets) {
+ boolean containsTests = false;
+ myTargets = targets;
+ myModules = new LinkedHashSet<JpsModule>();
+ for (ModuleBuildTarget target : targets) {
+ myModules.add(target.getModule());
+ containsTests |= target.isTests();
+ }
+ myContainsTests = containsTests;
+ }
+
+ public String getName() {
+ if (myModules.size() == 1) return myModules.iterator().next().getName();
+ return StringUtil.join(myModules, GET_NAME, ",");
+ }
+
+ public Set<JpsModule> getModules() {
+ return myModules;
+ }
+
+ public boolean containsTests() {
+ return myContainsTests;
+ }
+
+ public Set<ModuleBuildTarget> getTargets() {
+ return myTargets;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public ModuleBuildTarget representativeTarget() {
+ return myTargets.iterator().next();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java
new file mode 100644
index 000000000000..caa7e58a4338
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsSdkDependency;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/30/11
+ */
+public class ProjectPaths {
+ private ProjectPaths() {
+ }
+
+ public static Collection<File> getCompilationClasspathFiles(ModuleChunk chunk,
+ boolean includeTests,
+ final boolean excludeMainModuleOutput,
+ final boolean exportedOnly) {
+ return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(includeTests), excludeMainModuleOutput, ClasspathPart.WHOLE, exportedOnly);
+ }
+
+ public static Collection<File> getPlatformCompilationClasspath(ModuleChunk chunk, boolean excludeMainModuleOutput) {
+ return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.containsTests()), excludeMainModuleOutput, ClasspathPart.BEFORE_JDK, true);
+ }
+
+ public static Collection<File> getCompilationClasspath(ModuleChunk chunk, boolean excludeMainModuleOutput) {
+ return getClasspathFiles(chunk, JpsJavaClasspathKind.compile(chunk.containsTests()), excludeMainModuleOutput, ClasspathPart.AFTER_JDK, true);
+ }
+
+ private static Collection<File> getClasspathFiles(ModuleChunk chunk,
+ JpsJavaClasspathKind kind,
+ final boolean excludeMainModuleOutput,
+ ClasspathPart classpathPart, final boolean exportedOnly) {
+ final Set<File> files = new LinkedHashSet<File>();
+ for (JpsModule module : chunk.getModules()) {
+ JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(module).includedIn(kind).recursively();
+ if (exportedOnly) {
+ enumerator = enumerator.exportedOnly();
+ }
+ if (classpathPart == ClasspathPart.BEFORE_JDK) {
+ enumerator = enumerator.satisfying(new BeforeJavaSdkItemFilter(module));
+ }
+ else if (classpathPart == ClasspathPart.AFTER_JDK) {
+ enumerator = enumerator.satisfying(new AfterJavaSdkItemFilter(module));
+ }
+ JpsJavaDependenciesRootsEnumerator rootsEnumerator = enumerator.classes();
+ if (excludeMainModuleOutput) {
+ rootsEnumerator = rootsEnumerator.withoutSelfModuleOutput();
+ }
+ files.addAll(rootsEnumerator.getRoots());
+ }
+
+ if (classpathPart == ClasspathPart.BEFORE_JDK) {
+ for (JpsModule module : chunk.getModules()) {
+ JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE);
+ if (sdk != null) {
+ files.addAll(sdk.getParent().getFiles(JpsOrderRootType.COMPILED));
+ }
+ }
+ }
+ return files;
+ }
+
+ private static void addFile(Set<File> classpath, @Nullable String url) {
+ if (url != null) {
+ classpath.add(JpsPathUtil.urlToFile(url));
+ }
+ }
+
+ /**
+ *
+ * @param chunk
+ * @return mapping "sourceRoot" -> "package prefix" Package prefix uses slashes instead of dots and ends with trailing slash
+ */
+ @NotNull
+ public static Map<File, String> getSourceRootsWithDependents(ModuleChunk chunk) {
+ final boolean includeTests = chunk.containsTests();
+ final Map<File, String> result = new LinkedHashMap<File, String>();
+ processModulesRecursively(chunk, JpsJavaClasspathKind.compile(includeTests), new Consumer<JpsModule>() {
+ @Override
+ public void consume(JpsModule module) {
+ for (JpsModuleSourceRoot root : module.getSourceRoots()) {
+ if (root.getRootType().equals(JavaSourceRootType.SOURCE) ||
+ includeTests && root.getRootType().equals(JavaSourceRootType.TEST_SOURCE)) {
+ JavaSourceRootProperties properties = (JavaSourceRootProperties)((JpsSimpleElement<?>)root.getProperties()).getData();
+ String prefix = properties.getPackagePrefix();
+ if (!prefix.isEmpty()) {
+ prefix = prefix.replace('.', '/');
+ if (!prefix.endsWith("/")) {
+ prefix += "/";
+ }
+ }
+ else {
+ prefix = null;
+ }
+ result.put(JpsPathUtil.urlToFile(root.getUrl()), prefix);
+ }
+ }
+ }
+ });
+ return result;
+ }
+
+ public static Collection<File> getOutputPathsWithDependents(final ModuleChunk chunk) {
+ final boolean forTests = chunk.containsTests();
+ final Set<File> sourcePaths = new LinkedHashSet<File>();
+ processModulesRecursively(chunk, JpsJavaClasspathKind.compile(forTests), new Consumer<JpsModule>() {
+ @Override
+ public void consume(JpsModule module) {
+ addFile(sourcePaths, JpsJavaExtensionService.getInstance().getOutputUrl(module, forTests));
+ }
+ });
+ return sourcePaths;
+ }
+
+ public static Set<JpsModule> getModulesWithDependentsRecursively(final JpsModule module, final boolean includeTests) {
+ return JpsJavaExtensionService.dependencies(module).includedIn(JpsJavaClasspathKind.compile(includeTests)).recursively().getModules();
+ }
+
+ private static void processModulesRecursively(ModuleChunk chunk, JpsJavaClasspathKind kind, Consumer<JpsModule> processor) {
+ JpsJavaExtensionService.getInstance().enumerateDependencies(chunk.getModules()).includedIn(kind).recursively().processModules(processor);
+ }
+
+ @Nullable
+ public static File getModuleOutputDir(JpsModule module, boolean forTests) {
+ return JpsJavaExtensionService.getInstance().getOutputDirectory(module, forTests);
+ }
+
+ @Nullable
+ public static File getAnnotationProcessorGeneratedSourcesOutputDir(JpsModule module, final boolean forTests, ProcessorConfigProfile profile) {
+ final String sourceDirName = profile.getGeneratedSourcesDirectoryName(forTests);
+ if (profile.isOutputRelativeToContentRoot()) {
+ List<String> roots = module.getContentRootsList().getUrls();
+ if (roots.isEmpty()) {
+ return null;
+ }
+ if (roots.size() > 1) {
+ roots = new ArrayList<String>(roots); // sort roots to get deterministic result
+ Collections.sort(roots, new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return o1.compareTo(o2);
+ }
+ });
+ }
+ final File parent = JpsPathUtil.urlToFile(roots.get(0));
+ return StringUtil.isEmpty(sourceDirName)? parent : new File(parent, sourceDirName);
+ }
+
+ final File outputDir = getModuleOutputDir(module, forTests);
+ if (outputDir == null) {
+ return null;
+ }
+ return StringUtil.isEmpty(sourceDirName)? outputDir : new File(outputDir, sourceDirName);
+ }
+
+ private enum ClasspathPart {WHOLE, BEFORE_JDK, AFTER_JDK}
+
+ private static class BeforeJavaSdkItemFilter implements Condition<JpsDependencyElement> {
+ private JpsModule myModule;
+ private boolean mySdkFound;
+
+ private BeforeJavaSdkItemFilter(JpsModule module) {
+ myModule = module;
+ }
+
+ @Override
+ public boolean value(JpsDependencyElement dependency) {
+ boolean isJavaSdk = dependency instanceof JpsSdkDependency && ((JpsSdkDependency)dependency).getSdkType().equals(JpsJavaSdkType.INSTANCE);
+ if (myModule.equals(dependency.getContainingModule()) && isJavaSdk) {
+ mySdkFound = true;
+ }
+ return !mySdkFound && !isJavaSdk;
+ }
+ }
+
+ private static class AfterJavaSdkItemFilter implements Condition<JpsDependencyElement> {
+ private JpsModule myModule;
+ private boolean mySdkFound;
+
+ private AfterJavaSdkItemFilter(JpsModule module) {
+ myModule = module;
+ }
+
+ @Override
+ public boolean value(JpsDependencyElement dependency) {
+ if (myModule.equals(dependency.getContainingModule()) &&
+ dependency instanceof JpsSdkDependency && ((JpsSdkDependency)dependency).getSdkType().equals(JpsJavaSdkType.INSTANCE)) {
+ mySdkFound = true;
+ return false;
+ }
+ return mySdkFound;
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java b/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java
new file mode 100644
index 000000000000..4e4a6aaeac06
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 5/3/12
+ */
+public class BasicFuture<T> implements Future<T> {
+ protected final Semaphore mySemaphore = new Semaphore(1);
+ private final AtomicBoolean myDone = new AtomicBoolean(false);
+ private final AtomicBoolean myCanceledState = new AtomicBoolean(false);
+
+ public BasicFuture() {
+ }
+
+ public void setDone() {
+ if (!myDone.getAndSet(true)) {
+ mySemaphore.release();
+ }
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ if (isDone()) {
+ return false;
+ }
+ if (!myCanceledState.getAndSet(true)) {
+ try {
+ performCancel();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return true;
+ }
+
+ protected void performCancel() throws Exception {
+ }
+
+ public boolean isCancelled() {
+ return myCanceledState.get();
+ }
+
+ public boolean isDone() {
+ return myDone.get();
+ }
+
+ public void waitFor() {
+ try {
+ while (!isDone()) {
+ mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
+ }
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+
+ public boolean waitFor(long timeout, TimeUnit unit) {
+ try {
+ if (!isDone()) {
+ mySemaphore.tryAcquire(timeout, unit);
+ }
+ }
+ catch (InterruptedException ignored) {
+ }
+ return isDone();
+ }
+
+ public T get() throws InterruptedException, ExecutionException {
+ waitFor();
+ return null;
+ }
+
+ public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ if (!waitFor(timeout, unit)) {
+ throw new TimeoutException();
+ }
+ return null;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/BuildType.java b/jps/jps-builders/src/org/jetbrains/jps/api/BuildType.java
new file mode 100644
index 000000000000..5df39130c1b6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/BuildType.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 9/10/11
+*/
+public enum BuildType {
+ PROJECT_REBUILD, FORCED_COMPILATION, MAKE, CLEAN, UP_TO_DATE_CHECK
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/CanceledStatus.java b/jps/jps-builders/src/org/jetbrains/jps/api/CanceledStatus.java
new file mode 100644
index 000000000000..00c74ff4865d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/CanceledStatus.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/13/12
+*/
+public interface CanceledStatus {
+ CanceledStatus NULL = new CanceledStatus() {
+ @Override
+ public boolean isCanceled() {
+ return false;
+ }
+ };
+
+ boolean isCanceled();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java
new file mode 100644
index 000000000000..bc71808cf346
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.*;
+
+import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage;
+import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 4/17/12
+ */
+public class CmdlineProtoUtil {
+
+ public static CmdlineRemoteProto.Message.ControllerMessage createMakeRequest(String project,
+ List<TargetTypeBuildScope> scopes,
+ final Map<String, String> userData,
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals,
+ final @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) {
+ return createBuildParametersMessage(
+ CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.MAKE, project, scopes, userData, Collections.<String>emptyList(), globals, event
+ );
+ }
+
+ public static CmdlineRemoteProto.Message.ControllerMessage createUpToDateCheckRequest(String project,
+ List<TargetTypeBuildScope> scopes,
+ Collection<String> paths,
+ final Map<String, String> userData,
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals,
+ final @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) {
+ return createBuildParametersMessage(
+ CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.UP_TO_DATE_CHECK, project, scopes, userData, paths, globals, event
+ );
+ }
+
+ public static CmdlineRemoteProto.Message.ControllerMessage createForceCompileRequest(String project,
+ List<TargetTypeBuildScope> scopes,
+ Collection<String> paths,
+ final Map<String, String> userData,
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals,
+ final @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) {
+ return createBuildParametersMessage(CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.FORCED_COMPILATION, project,
+ scopes, userData, paths, globals, event);
+ }
+
+ public static CmdlineRemoteProto.Message.ControllerMessage createRebuildRequest(String project,
+ List<TargetTypeBuildScope> scopes,
+ final Map<String, String> userData,
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals) {
+ return createBuildParametersMessage(CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.REBUILD, project,
+ scopes, userData, Collections.<String>emptyList(),
+ globals, null);
+ }
+
+ public static List<TargetTypeBuildScope> createAllModulesScopes() {
+ return Arrays.asList(
+ createAllTargetsScope(JavaModuleBuildTargetType.PRODUCTION),
+ createAllTargetsScope(JavaModuleBuildTargetType.TEST)
+ );
+ }
+
+ public static TargetTypeBuildScope createAllTargetsScope(BuildTargetType<?> type) {
+ return TargetTypeBuildScope.newBuilder()
+ .setTypeId(type.getTypeId())
+ .setAllTargets(true)
+ .build();
+ }
+
+ private static CmdlineRemoteProto.Message.ControllerMessage createBuildParametersMessage(CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type buildType,
+ String project,
+ List<TargetTypeBuildScope> scopes,
+ Map<String, String> userData,
+ Collection<String> paths,
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals,
+ @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent initialEvent) {
+ final CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Builder
+ builder = CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.newBuilder();
+ builder.setGlobalSettings(globals);
+ builder.setBuildType(buildType);
+ builder.setProjectId(project);
+ builder.addAllScope(scopes);
+ if (!userData.isEmpty()) {
+ for (Map.Entry<String, String> entry : userData.entrySet()) {
+ final String key = entry.getKey();
+ final String value = entry.getValue();
+ if (key != null && value != null) {
+ builder.addBuilderParameter(createPair(key, value));
+ }
+ }
+ }
+ if (!paths.isEmpty()) {
+ builder.addAllFilePath(paths);
+ }
+ final CmdlineRemoteProto.Message.ControllerMessage.Builder controlMessageBuilder = CmdlineRemoteProto.Message.ControllerMessage.newBuilder();
+ if (initialEvent != null) {
+ controlMessageBuilder.setFsEvent(initialEvent);
+ }
+ return controlMessageBuilder.setType(CmdlineRemoteProto.Message.ControllerMessage.Type.BUILD_PARAMETERS).setParamsMessage(builder.build()).build();
+ }
+
+ public static CmdlineRemoteProto.Message.KeyValuePair createPair(String key, String value) {
+ return CmdlineRemoteProto.Message.KeyValuePair.newBuilder().setKey(key).setValue(value).build();
+ }
+
+
+ public static CmdlineRemoteProto.Message.Failure createFailure(String description, @Nullable Throwable cause) {
+ final CmdlineRemoteProto.Message.Failure.Builder builder = CmdlineRemoteProto.Message.Failure.newBuilder();
+ builder.setDescription(description);
+ if (cause != null) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream stream = new PrintStream(baos);
+ try {
+ cause.printStackTrace(stream);
+ }
+ finally {
+ stream.close();
+ }
+ builder.setStacktrace(new String(baos.toByteArray()));
+ }
+ return builder.build();
+ }
+
+ public static CmdlineRemoteProto.Message.ControllerMessage createCancelCommand() {
+ return CmdlineRemoteProto.Message.ControllerMessage.newBuilder()
+ .setType(CmdlineRemoteProto.Message.ControllerMessage.Type.CANCEL_BUILD_COMMAND).build();
+ }
+
+ public static BuilderMessage createCompileProgressMessageResponse(String text, float done) {
+ return createCompileMessage(BuildMessage.Kind.PROGRESS, text, null, -1L, -1L, -1L, -1, -1, done);
+ }
+
+ public static BuilderMessage createCompileMessage(final BuildMessage.Kind kind,
+ String text,
+ String path,
+ long beginOffset, long endOffset, long offset, long line,
+ long column, float done) {
+
+ final BuilderMessage.CompileMessage.Builder builder = BuilderMessage.CompileMessage.newBuilder();
+ switch (kind) {
+ case ERROR:
+ builder.setKind(BuilderMessage.CompileMessage.Kind.ERROR);
+ break;
+ case WARNING:
+ builder.setKind(BuilderMessage.CompileMessage.Kind.WARNING);
+ break;
+ case INFO:
+ builder.setKind(BuilderMessage.CompileMessage.Kind.INFO);
+ break;
+ default:
+ builder.setKind(BuilderMessage.CompileMessage.Kind.PROGRESS);
+ }
+ if (text != null) {
+ builder.setText(text);
+ }
+ if (path != null) {
+ builder.setSourceFilePath(path);
+ }
+ if (beginOffset >= 0L) {
+ builder.setProblemBeginOffset(beginOffset);
+ }
+ if (endOffset >= 0L) {
+ builder.setProblemEndOffset(endOffset);
+ }
+ if (offset >= 0L) {
+ builder.setProblemLocationOffset(offset);
+ }
+ if (line >= 0L) {
+ builder.setLine(line);
+ }
+ if (column >= 0L) {
+ builder.setColumn(column);
+ }
+ if (done >= 0.0f) {
+ builder.setDone(done);
+ }
+ return BuilderMessage.newBuilder().setType(BuilderMessage.Type.COMPILE_MESSAGE).setCompileMessage(builder.build()).build();
+ }
+
+ public static BuilderMessage createCustomBuilderMessage(String builderId, String messageType, String messageText) {
+ BuilderMessage.BuildEvent.CustomBuilderMessage builderMessage =
+ BuilderMessage.BuildEvent.CustomBuilderMessage.newBuilder()
+ .setBuilderId(builderId)
+ .setMessageType(messageType)
+ .setMessageText(messageText)
+ .build();
+ return createBuildEvent(BuilderMessage.BuildEvent.Type.CUSTOM_BUILDER_MESSAGE, null, null, null, builderMessage);
+ }
+
+ public static BuilderMessage createBuildCompletedEvent(@Nullable String description, final BuilderMessage.BuildEvent.Status status) {
+ return createBuildEvent(BuilderMessage.BuildEvent.Type.BUILD_COMPLETED, description, status, null, null);
+ }
+
+ public static BuilderMessage createFileGeneratedEvent(final Collection<Pair<String, String>> paths) {
+ return createBuildEvent(BuilderMessage.BuildEvent.Type.FILES_GENERATED, null, null, paths, null);
+ }
+
+ private static BuilderMessage createBuildEvent(final BuilderMessage.BuildEvent.Type type,
+ @Nullable String description,
+ @Nullable final BuilderMessage.BuildEvent.Status status,
+ @Nullable Collection<Pair<String, String>> generatedPaths,
+ @Nullable final BuilderMessage.BuildEvent.CustomBuilderMessage builderMessage) {
+ final BuilderMessage.BuildEvent.Builder builder = BuilderMessage.BuildEvent.newBuilder().setEventType(type);
+ if (description != null) {
+ builder.setDescription(description);
+ }
+ if (status != null) {
+ builder.setCompletionStatus(status);
+ }
+ if (generatedPaths != null) {
+ for (Pair<String, String> pair : generatedPaths) {
+ final BuilderMessage.BuildEvent.GeneratedFile.Builder fileBuilder = BuilderMessage.BuildEvent.GeneratedFile.newBuilder();
+ final BuilderMessage.BuildEvent.GeneratedFile generatedFile = fileBuilder.setOutputRoot(pair.first).setRelativePath(pair.second).build();
+ builder.addGeneratedFiles(generatedFile);
+ }
+ }
+ if (builderMessage != null) {
+ builder.setCustomBuilderMessage(builderMessage);
+ }
+ return BuilderMessage.newBuilder().setType(BuilderMessage.Type.BUILD_EVENT).setBuildEvent(builder.build()).build();
+ }
+
+ public static BuilderMessage createParamRequest() {
+ return BuilderMessage.newBuilder().setType(BuilderMessage.Type.PARAM_REQUEST).build();
+ }
+
+ public static CmdlineRemoteProto.Message toMessage(UUID sessionId, BuilderMessage builderMessage) {
+ return CmdlineRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setType(CmdlineRemoteProto.Message.Type.BUILDER_MESSAGE).setBuilderMessage(builderMessage).build();
+ }
+
+ public static CmdlineRemoteProto.Message toMessage(UUID sessionId, CmdlineRemoteProto.Message.ControllerMessage builderMessage) {
+ return CmdlineRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setType(CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE).setControllerMessage(
+ builderMessage).build();
+ }
+
+ public static CmdlineRemoteProto.Message toMessage(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
+ return CmdlineRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setType(CmdlineRemoteProto.Message.Type.FAILURE).setFailure(failure).build();
+ }
+
+ private static CmdlineRemoteProto.Message.UUID toProtoUUID(UUID sessionId) {
+ final CmdlineRemoteProto.Message.UUID.Builder uuidBuilder = CmdlineRemoteProto.Message.UUID.newBuilder();
+ return uuidBuilder.setMostSigBits(sessionId.getMostSignificantBits()).setLeastSigBits(sessionId.getLeastSignificantBits()).build();
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineRemoteProto.java b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineRemoteProto.java
new file mode 100644
index 000000000000..4d7b8cb35bdb
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineRemoteProto.java
@@ -0,0 +1,9578 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: cmdline_remote_proto.proto
+
+package org.jetbrains.jps.api;
+
+public final class CmdlineRemoteProto {
+ private CmdlineRemoteProto() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+ public interface MessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.UUID session_id = 1;
+ boolean hasSessionId();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID getSessionId();
+
+ // required .org.jetbrains.jpsservice.Message.Type type = 2;
+ boolean hasType();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type getType();
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage controller_message = 3;
+ boolean hasControllerMessage();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage getControllerMessage();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage builder_message = 4;
+ boolean hasBuilderMessage();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage getBuilderMessage();
+
+ // optional .org.jetbrains.jpsservice.Message.Failure failure = 5;
+ boolean hasFailure();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure getFailure();
+ }
+ public static final class Message extends
+ com.google.protobuf.GeneratedMessageLite
+ implements MessageOrBuilder {
+ // Use Message.newBuilder() to construct.
+ private Message(Builder builder) {
+ super(builder);
+ }
+ private Message(boolean noInit) {}
+
+ private static final Message defaultInstance;
+ public static Message getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Message getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ CONTROLLER_MESSAGE(0, 1),
+ BUILDER_MESSAGE(1, 2),
+ FAILURE(2, 3),
+ ;
+
+ public static final int CONTROLLER_MESSAGE_VALUE = 1;
+ public static final int BUILDER_MESSAGE_VALUE = 2;
+ public static final int FAILURE_VALUE = 3;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return CONTROLLER_MESSAGE;
+ case 2: return BUILDER_MESSAGE;
+ case 3: return FAILURE;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.Type)
+ }
+
+ public interface UUIDOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required sint64 most_sig_bits = 1;
+ boolean hasMostSigBits();
+ long getMostSigBits();
+
+ // required sint64 least_sig_bits = 2;
+ boolean hasLeastSigBits();
+ long getLeastSigBits();
+ }
+ public static final class UUID extends
+ com.google.protobuf.GeneratedMessageLite
+ implements UUIDOrBuilder {
+ // Use UUID.newBuilder() to construct.
+ private UUID(Builder builder) {
+ super(builder);
+ }
+ private UUID(boolean noInit) {}
+
+ private static final UUID defaultInstance;
+ public static UUID getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public UUID getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required sint64 most_sig_bits = 1;
+ public static final int MOST_SIG_BITS_FIELD_NUMBER = 1;
+ private long mostSigBits_;
+ public boolean hasMostSigBits() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getMostSigBits() {
+ return mostSigBits_;
+ }
+
+ // required sint64 least_sig_bits = 2;
+ public static final int LEAST_SIG_BITS_FIELD_NUMBER = 2;
+ private long leastSigBits_;
+ public boolean hasLeastSigBits() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public long getLeastSigBits() {
+ return leastSigBits_;
+ }
+
+ private void initFields() {
+ mostSigBits_ = 0L;
+ leastSigBits_ = 0L;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasMostSigBits()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasLeastSigBits()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeSInt64(1, mostSigBits_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeSInt64(2, leastSigBits_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeSInt64Size(1, mostSigBits_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeSInt64Size(2, leastSigBits_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUIDOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ mostSigBits_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ leastSigBits_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.mostSigBits_ = mostSigBits_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.leastSigBits_ = leastSigBits_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance()) return this;
+ if (other.hasMostSigBits()) {
+ setMostSigBits(other.getMostSigBits());
+ }
+ if (other.hasLeastSigBits()) {
+ setLeastSigBits(other.getLeastSigBits());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasMostSigBits()) {
+
+ return false;
+ }
+ if (!hasLeastSigBits()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ mostSigBits_ = input.readSInt64();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ leastSigBits_ = input.readSInt64();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required sint64 most_sig_bits = 1;
+ private long mostSigBits_ ;
+ public boolean hasMostSigBits() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getMostSigBits() {
+ return mostSigBits_;
+ }
+ public Builder setMostSigBits(long value) {
+ bitField0_ |= 0x00000001;
+ mostSigBits_ = value;
+
+ return this;
+ }
+ public Builder clearMostSigBits() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ mostSigBits_ = 0L;
+
+ return this;
+ }
+
+ // required sint64 least_sig_bits = 2;
+ private long leastSigBits_ ;
+ public boolean hasLeastSigBits() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public long getLeastSigBits() {
+ return leastSigBits_;
+ }
+ public Builder setLeastSigBits(long value) {
+ bitField0_ |= 0x00000002;
+ leastSigBits_ = value;
+
+ return this;
+ }
+ public Builder clearLeastSigBits() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ leastSigBits_ = 0L;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.UUID)
+ }
+
+ static {
+ defaultInstance = new UUID(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.UUID)
+ }
+
+ public interface KeyValuePairOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string key = 1;
+ boolean hasKey();
+ String getKey();
+
+ // required string value = 2;
+ boolean hasValue();
+ String getValue();
+ }
+ public static final class KeyValuePair extends
+ com.google.protobuf.GeneratedMessageLite
+ implements KeyValuePairOrBuilder {
+ // Use KeyValuePair.newBuilder() to construct.
+ private KeyValuePair(Builder builder) {
+ super(builder);
+ }
+ private KeyValuePair(boolean noInit) {}
+
+ private static final KeyValuePair defaultInstance;
+ public static KeyValuePair getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public KeyValuePair getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string key = 1;
+ public static final int KEY_FIELD_NUMBER = 1;
+ private java.lang.Object key_;
+ public boolean hasKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getKey() {
+ java.lang.Object ref = key_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ key_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getKeyBytes() {
+ java.lang.Object ref = key_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ key_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string value = 2;
+ public static final int VALUE_FIELD_NUMBER = 2;
+ private java.lang.Object value_;
+ public boolean hasValue() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getValue() {
+ java.lang.Object ref = value_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ value_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getValueBytes() {
+ java.lang.Object ref = value_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ value_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ key_ = "";
+ value_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasKey()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasValue()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getKeyBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getValueBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getKeyBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getValueBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePairOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ key_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ value_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.key_ = key_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.value_ = value_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.getDefaultInstance()) return this;
+ if (other.hasKey()) {
+ setKey(other.getKey());
+ }
+ if (other.hasValue()) {
+ setValue(other.getValue());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasKey()) {
+
+ return false;
+ }
+ if (!hasValue()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ key_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ value_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string key = 1;
+ private java.lang.Object key_ = "";
+ public boolean hasKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getKey() {
+ java.lang.Object ref = key_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ key_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setKey(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ key_ = value;
+
+ return this;
+ }
+ public Builder clearKey() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ key_ = getDefaultInstance().getKey();
+
+ return this;
+ }
+ void setKey(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ key_ = value;
+
+ }
+
+ // required string value = 2;
+ private java.lang.Object value_ = "";
+ public boolean hasValue() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getValue() {
+ java.lang.Object ref = value_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ value_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setValue(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ value_ = value;
+
+ return this;
+ }
+ public Builder clearValue() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ value_ = getDefaultInstance().getValue();
+
+ return this;
+ }
+ void setValue(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ value_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.KeyValuePair)
+ }
+
+ static {
+ defaultInstance = new KeyValuePair(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.KeyValuePair)
+ }
+
+ public interface FailureOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // optional int32 error_code = 1;
+ boolean hasErrorCode();
+ int getErrorCode();
+
+ // optional string description = 2;
+ boolean hasDescription();
+ String getDescription();
+
+ // optional string stacktrace = 3;
+ boolean hasStacktrace();
+ String getStacktrace();
+ }
+ public static final class Failure extends
+ com.google.protobuf.GeneratedMessageLite
+ implements FailureOrBuilder {
+ // Use Failure.newBuilder() to construct.
+ private Failure(Builder builder) {
+ super(builder);
+ }
+ private Failure(boolean noInit) {}
+
+ private static final Failure defaultInstance;
+ public static Failure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Failure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // optional int32 error_code = 1;
+ public static final int ERROR_CODE_FIELD_NUMBER = 1;
+ private int errorCode_;
+ public boolean hasErrorCode() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public int getErrorCode() {
+ return errorCode_;
+ }
+
+ // optional string description = 2;
+ public static final int DESCRIPTION_FIELD_NUMBER = 2;
+ private java.lang.Object description_;
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ description_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getDescriptionBytes() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ description_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string stacktrace = 3;
+ public static final int STACKTRACE_FIELD_NUMBER = 3;
+ private java.lang.Object stacktrace_;
+ public boolean hasStacktrace() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getStacktrace() {
+ java.lang.Object ref = stacktrace_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ stacktrace_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getStacktraceBytes() {
+ java.lang.Object ref = stacktrace_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ stacktrace_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ errorCode_ = 0;
+ description_ = "";
+ stacktrace_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(1, errorCode_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getStacktraceBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, errorCode_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getStacktraceBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.FailureOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ errorCode_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ description_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ stacktrace_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.errorCode_ = errorCode_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.description_ = description_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.stacktrace_ = stacktrace_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance()) return this;
+ if (other.hasErrorCode()) {
+ setErrorCode(other.getErrorCode());
+ }
+ if (other.hasDescription()) {
+ setDescription(other.getDescription());
+ }
+ if (other.hasStacktrace()) {
+ setStacktrace(other.getStacktrace());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ errorCode_ = input.readInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ description_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ stacktrace_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // optional int32 error_code = 1;
+ private int errorCode_ ;
+ public boolean hasErrorCode() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public int getErrorCode() {
+ return errorCode_;
+ }
+ public Builder setErrorCode(int value) {
+ bitField0_ |= 0x00000001;
+ errorCode_ = value;
+
+ return this;
+ }
+ public Builder clearErrorCode() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ errorCode_ = 0;
+
+ return this;
+ }
+
+ // optional string description = 2;
+ private java.lang.Object description_ = "";
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ description_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setDescription(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ return this;
+ }
+ public Builder clearDescription() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ description_ = getDefaultInstance().getDescription();
+
+ return this;
+ }
+ void setDescription(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ }
+
+ // optional string stacktrace = 3;
+ private java.lang.Object stacktrace_ = "";
+ public boolean hasStacktrace() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getStacktrace() {
+ java.lang.Object ref = stacktrace_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ stacktrace_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setStacktrace(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ stacktrace_ = value;
+
+ return this;
+ }
+ public Builder clearStacktrace() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ stacktrace_ = getDefaultInstance().getStacktrace();
+
+ return this;
+ }
+ void setStacktrace(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ stacktrace_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.Failure)
+ }
+
+ static {
+ defaultInstance = new Failure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.Failure)
+ }
+
+ public interface ControllerMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.Type type = 1;
+ boolean hasType();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type getType();
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage params_message = 2;
+ boolean hasParamsMessage();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage getParamsMessage();
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.FSEvent fs_event = 3;
+ boolean hasFsEvent();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent getFsEvent();
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ConstantSearchResult constant_search_result = 4;
+ boolean hasConstantSearchResult();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult getConstantSearchResult();
+ }
+ public static final class ControllerMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ControllerMessageOrBuilder {
+ // Use ControllerMessage.newBuilder() to construct.
+ private ControllerMessage(Builder builder) {
+ super(builder);
+ }
+ private ControllerMessage(boolean noInit) {}
+
+ private static final ControllerMessage defaultInstance;
+ public static ControllerMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ControllerMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ BUILD_PARAMETERS(0, 1),
+ CANCEL_BUILD_COMMAND(1, 2),
+ FS_EVENT(2, 3),
+ CONSTANT_SEARCH_RESULT(3, 4),
+ ;
+
+ public static final int BUILD_PARAMETERS_VALUE = 1;
+ public static final int CANCEL_BUILD_COMMAND_VALUE = 2;
+ public static final int FS_EVENT_VALUE = 3;
+ public static final int CONSTANT_SEARCH_RESULT_VALUE = 4;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return BUILD_PARAMETERS;
+ case 2: return CANCEL_BUILD_COMMAND;
+ case 3: return FS_EVENT;
+ case 4: return CONSTANT_SEARCH_RESULT;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.ControllerMessage.Type)
+ }
+
+ public interface FSEventOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required uint64 ordinal = 1;
+ boolean hasOrdinal();
+ long getOrdinal();
+
+ // repeated string changed_paths = 2;
+ java.util.List<String> getChangedPathsList();
+ int getChangedPathsCount();
+ String getChangedPaths(int index);
+
+ // repeated string deleted_paths = 3;
+ java.util.List<String> getDeletedPathsList();
+ int getDeletedPathsCount();
+ String getDeletedPaths(int index);
+ }
+ public static final class FSEvent extends
+ com.google.protobuf.GeneratedMessageLite
+ implements FSEventOrBuilder {
+ // Use FSEvent.newBuilder() to construct.
+ private FSEvent(Builder builder) {
+ super(builder);
+ }
+ private FSEvent(boolean noInit) {}
+
+ private static final FSEvent defaultInstance;
+ public static FSEvent getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public FSEvent getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required uint64 ordinal = 1;
+ public static final int ORDINAL_FIELD_NUMBER = 1;
+ private long ordinal_;
+ public boolean hasOrdinal() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getOrdinal() {
+ return ordinal_;
+ }
+
+ // repeated string changed_paths = 2;
+ public static final int CHANGED_PATHS_FIELD_NUMBER = 2;
+ private com.google.protobuf.LazyStringList changedPaths_;
+ public java.util.List<String>
+ getChangedPathsList() {
+ return changedPaths_;
+ }
+ public int getChangedPathsCount() {
+ return changedPaths_.size();
+ }
+ public String getChangedPaths(int index) {
+ return changedPaths_.get(index);
+ }
+
+ // repeated string deleted_paths = 3;
+ public static final int DELETED_PATHS_FIELD_NUMBER = 3;
+ private com.google.protobuf.LazyStringList deletedPaths_;
+ public java.util.List<String>
+ getDeletedPathsList() {
+ return deletedPaths_;
+ }
+ public int getDeletedPathsCount() {
+ return deletedPaths_.size();
+ }
+ public String getDeletedPaths(int index) {
+ return deletedPaths_.get(index);
+ }
+
+ private void initFields() {
+ ordinal_ = 0L;
+ changedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ deletedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasOrdinal()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt64(1, ordinal_);
+ }
+ for (int i = 0; i < changedPaths_.size(); i++) {
+ output.writeBytes(2, changedPaths_.getByteString(i));
+ }
+ for (int i = 0; i < deletedPaths_.size(); i++) {
+ output.writeBytes(3, deletedPaths_.getByteString(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(1, ordinal_);
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < changedPaths_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(changedPaths_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getChangedPathsList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < deletedPaths_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(deletedPaths_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getDeletedPathsList().size();
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEventOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ ordinal_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ changedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ deletedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.ordinal_ = ordinal_;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ changedPaths_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ changedPaths_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.changedPaths_ = changedPaths_;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ deletedPaths_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ deletedPaths_);
+ bitField0_ = (bitField0_ & ~0x00000004);
+ }
+ result.deletedPaths_ = deletedPaths_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance()) return this;
+ if (other.hasOrdinal()) {
+ setOrdinal(other.getOrdinal());
+ }
+ if (!other.changedPaths_.isEmpty()) {
+ if (changedPaths_.isEmpty()) {
+ changedPaths_ = other.changedPaths_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensureChangedPathsIsMutable();
+ changedPaths_.addAll(other.changedPaths_);
+ }
+
+ }
+ if (!other.deletedPaths_.isEmpty()) {
+ if (deletedPaths_.isEmpty()) {
+ deletedPaths_ = other.deletedPaths_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureDeletedPathsIsMutable();
+ deletedPaths_.addAll(other.deletedPaths_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasOrdinal()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ ordinal_ = input.readUInt64();
+ break;
+ }
+ case 18: {
+ ensureChangedPathsIsMutable();
+ changedPaths_.add(input.readBytes());
+ break;
+ }
+ case 26: {
+ ensureDeletedPathsIsMutable();
+ deletedPaths_.add(input.readBytes());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required uint64 ordinal = 1;
+ private long ordinal_ ;
+ public boolean hasOrdinal() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getOrdinal() {
+ return ordinal_;
+ }
+ public Builder setOrdinal(long value) {
+ bitField0_ |= 0x00000001;
+ ordinal_ = value;
+
+ return this;
+ }
+ public Builder clearOrdinal() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ ordinal_ = 0L;
+
+ return this;
+ }
+
+ // repeated string changed_paths = 2;
+ private com.google.protobuf.LazyStringList changedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureChangedPathsIsMutable() {
+ if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+ changedPaths_ = new com.google.protobuf.LazyStringArrayList(changedPaths_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+ public java.util.List<String>
+ getChangedPathsList() {
+ return java.util.Collections.unmodifiableList(changedPaths_);
+ }
+ public int getChangedPathsCount() {
+ return changedPaths_.size();
+ }
+ public String getChangedPaths(int index) {
+ return changedPaths_.get(index);
+ }
+ public Builder setChangedPaths(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureChangedPathsIsMutable();
+ changedPaths_.set(index, value);
+
+ return this;
+ }
+ public Builder addChangedPaths(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureChangedPathsIsMutable();
+ changedPaths_.add(value);
+
+ return this;
+ }
+ public Builder addAllChangedPaths(
+ java.lang.Iterable<String> values) {
+ ensureChangedPathsIsMutable();
+ super.addAll(values, changedPaths_);
+
+ return this;
+ }
+ public Builder clearChangedPaths() {
+ changedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+
+ return this;
+ }
+ void addChangedPaths(com.google.protobuf.ByteString value) {
+ ensureChangedPathsIsMutable();
+ changedPaths_.add(value);
+
+ }
+
+ // repeated string deleted_paths = 3;
+ private com.google.protobuf.LazyStringList deletedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureDeletedPathsIsMutable() {
+ if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+ deletedPaths_ = new com.google.protobuf.LazyStringArrayList(deletedPaths_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+ public java.util.List<String>
+ getDeletedPathsList() {
+ return java.util.Collections.unmodifiableList(deletedPaths_);
+ }
+ public int getDeletedPathsCount() {
+ return deletedPaths_.size();
+ }
+ public String getDeletedPaths(int index) {
+ return deletedPaths_.get(index);
+ }
+ public Builder setDeletedPaths(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureDeletedPathsIsMutable();
+ deletedPaths_.set(index, value);
+
+ return this;
+ }
+ public Builder addDeletedPaths(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureDeletedPathsIsMutable();
+ deletedPaths_.add(value);
+
+ return this;
+ }
+ public Builder addAllDeletedPaths(
+ java.lang.Iterable<String> values) {
+ ensureDeletedPathsIsMutable();
+ super.addAll(values, deletedPaths_);
+
+ return this;
+ }
+ public Builder clearDeletedPaths() {
+ deletedPaths_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+
+ return this;
+ }
+ void addDeletedPaths(com.google.protobuf.ByteString value) {
+ ensureDeletedPathsIsMutable();
+ deletedPaths_.add(value);
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.FSEvent)
+ }
+
+ static {
+ defaultInstance = new FSEvent(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage.FSEvent)
+ }
+
+ public interface GlobalSettingsOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair path_variable = 1;
+ java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair>
+ getPathVariableList();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getPathVariable(int index);
+ int getPathVariableCount();
+
+ // required string global_options_path = 5;
+ boolean hasGlobalOptionsPath();
+ String getGlobalOptionsPath();
+ }
+ public static final class GlobalSettings extends
+ com.google.protobuf.GeneratedMessageLite
+ implements GlobalSettingsOrBuilder {
+ // Use GlobalSettings.newBuilder() to construct.
+ private GlobalSettings(Builder builder) {
+ super(builder);
+ }
+ private GlobalSettings(boolean noInit) {}
+
+ private static final GlobalSettings defaultInstance;
+ public static GlobalSettings getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public GlobalSettings getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair path_variable = 1;
+ public static final int PATH_VARIABLE_FIELD_NUMBER = 1;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> pathVariable_;
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> getPathVariableList() {
+ return pathVariable_;
+ }
+ public java.util.List<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePairOrBuilder>
+ getPathVariableOrBuilderList() {
+ return pathVariable_;
+ }
+ public int getPathVariableCount() {
+ return pathVariable_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getPathVariable(int index) {
+ return pathVariable_.get(index);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePairOrBuilder getPathVariableOrBuilder(
+ int index) {
+ return pathVariable_.get(index);
+ }
+
+ // required string global_options_path = 5;
+ public static final int GLOBAL_OPTIONS_PATH_FIELD_NUMBER = 5;
+ private java.lang.Object globalOptionsPath_;
+ public boolean hasGlobalOptionsPath() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getGlobalOptionsPath() {
+ java.lang.Object ref = globalOptionsPath_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ globalOptionsPath_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getGlobalOptionsPathBytes() {
+ java.lang.Object ref = globalOptionsPath_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ globalOptionsPath_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ pathVariable_ = java.util.Collections.emptyList();
+ globalOptionsPath_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasGlobalOptionsPath()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ for (int i = 0; i < getPathVariableCount(); i++) {
+ if (!getPathVariable(i).isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ for (int i = 0; i < pathVariable_.size(); i++) {
+ output.writeMessage(1, pathVariable_.get(i));
+ }
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(5, getGlobalOptionsPathBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (int i = 0; i < pathVariable_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, pathVariable_.get(i));
+ }
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(5, getGlobalOptionsPathBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettingsOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ pathVariable_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ globalOptionsPath_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ pathVariable_ = java.util.Collections.unmodifiableList(pathVariable_);
+ bitField0_ = (bitField0_ & ~0x00000001);
+ }
+ result.pathVariable_ = pathVariable_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.globalOptionsPath_ = globalOptionsPath_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance()) return this;
+ if (!other.pathVariable_.isEmpty()) {
+ if (pathVariable_.isEmpty()) {
+ pathVariable_ = other.pathVariable_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ ensurePathVariableIsMutable();
+ pathVariable_.addAll(other.pathVariable_);
+ }
+
+ }
+ if (other.hasGlobalOptionsPath()) {
+ setGlobalOptionsPath(other.getGlobalOptionsPath());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasGlobalOptionsPath()) {
+
+ return false;
+ }
+ for (int i = 0; i < getPathVariableCount(); i++) {
+ if (!getPathVariable(i).isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addPathVariable(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ bitField0_ |= 0x00000002;
+ globalOptionsPath_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair path_variable = 1;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> pathVariable_ =
+ java.util.Collections.emptyList();
+ private void ensurePathVariableIsMutable() {
+ if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+ pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair>(pathVariable_);
+ bitField0_ |= 0x00000001;
+ }
+ }
+
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> getPathVariableList() {
+ return java.util.Collections.unmodifiableList(pathVariable_);
+ }
+ public int getPathVariableCount() {
+ return pathVariable_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getPathVariable(int index) {
+ return pathVariable_.get(index);
+ }
+ public Builder setPathVariable(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePathVariableIsMutable();
+ pathVariable_.set(index, value);
+
+ return this;
+ }
+ public Builder setPathVariable(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensurePathVariableIsMutable();
+ pathVariable_.set(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addPathVariable(org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePathVariableIsMutable();
+ pathVariable_.add(value);
+
+ return this;
+ }
+ public Builder addPathVariable(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePathVariableIsMutable();
+ pathVariable_.add(index, value);
+
+ return this;
+ }
+ public Builder addPathVariable(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensurePathVariableIsMutable();
+ pathVariable_.add(builderForValue.build());
+
+ return this;
+ }
+ public Builder addPathVariable(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensurePathVariableIsMutable();
+ pathVariable_.add(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addAllPathVariable(
+ java.lang.Iterable<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> values) {
+ ensurePathVariableIsMutable();
+ super.addAll(values, pathVariable_);
+
+ return this;
+ }
+ public Builder clearPathVariable() {
+ pathVariable_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+
+ return this;
+ }
+ public Builder removePathVariable(int index) {
+ ensurePathVariableIsMutable();
+ pathVariable_.remove(index);
+
+ return this;
+ }
+
+ // required string global_options_path = 5;
+ private java.lang.Object globalOptionsPath_ = "";
+ public boolean hasGlobalOptionsPath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getGlobalOptionsPath() {
+ java.lang.Object ref = globalOptionsPath_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ globalOptionsPath_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setGlobalOptionsPath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ globalOptionsPath_ = value;
+
+ return this;
+ }
+ public Builder clearGlobalOptionsPath() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ globalOptionsPath_ = getDefaultInstance().getGlobalOptionsPath();
+
+ return this;
+ }
+ void setGlobalOptionsPath(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ globalOptionsPath_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.GlobalSettings)
+ }
+
+ static {
+ defaultInstance = new GlobalSettings(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage.GlobalSettings)
+ }
+
+ public interface ParametersMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.Type build_type = 1;
+ boolean hasBuildType();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type getBuildType();
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.GlobalSettings global_settings = 2;
+ boolean hasGlobalSettings();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings getGlobalSettings();
+
+ // optional string project_id = 3;
+ boolean hasProjectId();
+ String getProjectId();
+
+ // repeated .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope scope = 4;
+ java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope>
+ getScopeList();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope getScope(int index);
+ int getScopeCount();
+
+ // repeated string file_path = 5;
+ java.util.List<String> getFilePathList();
+ int getFilePathCount();
+ String getFilePath(int index);
+
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair builder_parameter = 6;
+ java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair>
+ getBuilderParameterList();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getBuilderParameter(int index);
+ int getBuilderParameterCount();
+ }
+ public static final class ParametersMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ParametersMessageOrBuilder {
+ // Use ParametersMessage.newBuilder() to construct.
+ private ParametersMessage(Builder builder) {
+ super(builder);
+ }
+ private ParametersMessage(boolean noInit) {}
+
+ private static final ParametersMessage defaultInstance;
+ public static ParametersMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ParametersMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ REBUILD(0, 1),
+ MAKE(1, 2),
+ CLEAN(2, 3),
+ FORCED_COMPILATION(3, 4),
+ UP_TO_DATE_CHECK(4, 5),
+ ;
+
+ public static final int REBUILD_VALUE = 1;
+ public static final int MAKE_VALUE = 2;
+ public static final int CLEAN_VALUE = 3;
+ public static final int FORCED_COMPILATION_VALUE = 4;
+ public static final int UP_TO_DATE_CHECK_VALUE = 5;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return REBUILD;
+ case 2: return MAKE;
+ case 3: return CLEAN;
+ case 4: return FORCED_COMPILATION;
+ case 5: return UP_TO_DATE_CHECK;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.Type)
+ }
+
+ public interface TargetTypeBuildScopeOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string type_id = 1;
+ boolean hasTypeId();
+ String getTypeId();
+
+ // optional bool all_targets = 2;
+ boolean hasAllTargets();
+ boolean getAllTargets();
+
+ // repeated string target_id = 3;
+ java.util.List<String> getTargetIdList();
+ int getTargetIdCount();
+ String getTargetId(int index);
+ }
+ public static final class TargetTypeBuildScope extends
+ com.google.protobuf.GeneratedMessageLite
+ implements TargetTypeBuildScopeOrBuilder {
+ // Use TargetTypeBuildScope.newBuilder() to construct.
+ private TargetTypeBuildScope(Builder builder) {
+ super(builder);
+ }
+ private TargetTypeBuildScope(boolean noInit) {}
+
+ private static final TargetTypeBuildScope defaultInstance;
+ public static TargetTypeBuildScope getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public TargetTypeBuildScope getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string type_id = 1;
+ public static final int TYPE_ID_FIELD_NUMBER = 1;
+ private java.lang.Object typeId_;
+ public boolean hasTypeId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getTypeId() {
+ java.lang.Object ref = typeId_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ typeId_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getTypeIdBytes() {
+ java.lang.Object ref = typeId_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ typeId_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional bool all_targets = 2;
+ public static final int ALL_TARGETS_FIELD_NUMBER = 2;
+ private boolean allTargets_;
+ public boolean hasAllTargets() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public boolean getAllTargets() {
+ return allTargets_;
+ }
+
+ // repeated string target_id = 3;
+ public static final int TARGET_ID_FIELD_NUMBER = 3;
+ private com.google.protobuf.LazyStringList targetId_;
+ public java.util.List<String>
+ getTargetIdList() {
+ return targetId_;
+ }
+ public int getTargetIdCount() {
+ return targetId_.size();
+ }
+ public String getTargetId(int index) {
+ return targetId_.get(index);
+ }
+
+ private void initFields() {
+ typeId_ = "";
+ allTargets_ = false;
+ targetId_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasTypeId()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getTypeIdBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBool(2, allTargets_);
+ }
+ for (int i = 0; i < targetId_.size(); i++) {
+ output.writeBytes(3, targetId_.getByteString(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getTypeIdBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(2, allTargets_);
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < targetId_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(targetId_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getTargetIdList().size();
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScopeOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ typeId_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ allTargets_ = false;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ targetId_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.typeId_ = typeId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.allTargets_ = allTargets_;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ targetId_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ targetId_);
+ bitField0_ = (bitField0_ & ~0x00000004);
+ }
+ result.targetId_ = targetId_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.getDefaultInstance()) return this;
+ if (other.hasTypeId()) {
+ setTypeId(other.getTypeId());
+ }
+ if (other.hasAllTargets()) {
+ setAllTargets(other.getAllTargets());
+ }
+ if (!other.targetId_.isEmpty()) {
+ if (targetId_.isEmpty()) {
+ targetId_ = other.targetId_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureTargetIdIsMutable();
+ targetId_.addAll(other.targetId_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasTypeId()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ typeId_ = input.readBytes();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ allTargets_ = input.readBool();
+ break;
+ }
+ case 26: {
+ ensureTargetIdIsMutable();
+ targetId_.add(input.readBytes());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string type_id = 1;
+ private java.lang.Object typeId_ = "";
+ public boolean hasTypeId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getTypeId() {
+ java.lang.Object ref = typeId_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ typeId_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setTypeId(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ typeId_ = value;
+
+ return this;
+ }
+ public Builder clearTypeId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ typeId_ = getDefaultInstance().getTypeId();
+
+ return this;
+ }
+ void setTypeId(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ typeId_ = value;
+
+ }
+
+ // optional bool all_targets = 2;
+ private boolean allTargets_ ;
+ public boolean hasAllTargets() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public boolean getAllTargets() {
+ return allTargets_;
+ }
+ public Builder setAllTargets(boolean value) {
+ bitField0_ |= 0x00000002;
+ allTargets_ = value;
+
+ return this;
+ }
+ public Builder clearAllTargets() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ allTargets_ = false;
+
+ return this;
+ }
+
+ // repeated string target_id = 3;
+ private com.google.protobuf.LazyStringList targetId_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureTargetIdIsMutable() {
+ if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+ targetId_ = new com.google.protobuf.LazyStringArrayList(targetId_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+ public java.util.List<String>
+ getTargetIdList() {
+ return java.util.Collections.unmodifiableList(targetId_);
+ }
+ public int getTargetIdCount() {
+ return targetId_.size();
+ }
+ public String getTargetId(int index) {
+ return targetId_.get(index);
+ }
+ public Builder setTargetId(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureTargetIdIsMutable();
+ targetId_.set(index, value);
+
+ return this;
+ }
+ public Builder addTargetId(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureTargetIdIsMutable();
+ targetId_.add(value);
+
+ return this;
+ }
+ public Builder addAllTargetId(
+ java.lang.Iterable<String> values) {
+ ensureTargetIdIsMutable();
+ super.addAll(values, targetId_);
+
+ return this;
+ }
+ public Builder clearTargetId() {
+ targetId_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+
+ return this;
+ }
+ void addTargetId(com.google.protobuf.ByteString value) {
+ ensureTargetIdIsMutable();
+ targetId_.add(value);
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope)
+ }
+
+ static {
+ defaultInstance = new TargetTypeBuildScope(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.Type build_type = 1;
+ public static final int BUILD_TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type buildType_;
+ public boolean hasBuildType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type getBuildType() {
+ return buildType_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.GlobalSettings global_settings = 2;
+ public static final int GLOBAL_SETTINGS_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globalSettings_;
+ public boolean hasGlobalSettings() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings getGlobalSettings() {
+ return globalSettings_;
+ }
+
+ // optional string project_id = 3;
+ public static final int PROJECT_ID_FIELD_NUMBER = 3;
+ private java.lang.Object projectId_;
+ public boolean hasProjectId() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getProjectId() {
+ java.lang.Object ref = projectId_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ projectId_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getProjectIdBytes() {
+ java.lang.Object ref = projectId_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ projectId_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope scope = 4;
+ public static final int SCOPE_FIELD_NUMBER = 4;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> scope_;
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> getScopeList() {
+ return scope_;
+ }
+ public java.util.List<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScopeOrBuilder>
+ getScopeOrBuilderList() {
+ return scope_;
+ }
+ public int getScopeCount() {
+ return scope_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope getScope(int index) {
+ return scope_.get(index);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScopeOrBuilder getScopeOrBuilder(
+ int index) {
+ return scope_.get(index);
+ }
+
+ // repeated string file_path = 5;
+ public static final int FILE_PATH_FIELD_NUMBER = 5;
+ private com.google.protobuf.LazyStringList filePath_;
+ public java.util.List<String>
+ getFilePathList() {
+ return filePath_;
+ }
+ public int getFilePathCount() {
+ return filePath_.size();
+ }
+ public String getFilePath(int index) {
+ return filePath_.get(index);
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair builder_parameter = 6;
+ public static final int BUILDER_PARAMETER_FIELD_NUMBER = 6;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> builderParameter_;
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> getBuilderParameterList() {
+ return builderParameter_;
+ }
+ public java.util.List<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePairOrBuilder>
+ getBuilderParameterOrBuilderList() {
+ return builderParameter_;
+ }
+ public int getBuilderParameterCount() {
+ return builderParameter_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getBuilderParameter(int index) {
+ return builderParameter_.get(index);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePairOrBuilder getBuilderParameterOrBuilder(
+ int index) {
+ return builderParameter_.get(index);
+ }
+
+ private void initFields() {
+ buildType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.REBUILD;
+ globalSettings_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance();
+ projectId_ = "";
+ scope_ = java.util.Collections.emptyList();
+ filePath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ builderParameter_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasBuildType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasGlobalSettings()) {
+ if (!getGlobalSettings().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ for (int i = 0; i < getScopeCount(); i++) {
+ if (!getScope(i).isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ for (int i = 0; i < getBuilderParameterCount(); i++) {
+ if (!getBuilderParameter(i).isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, buildType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, globalSettings_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getProjectIdBytes());
+ }
+ for (int i = 0; i < scope_.size(); i++) {
+ output.writeMessage(4, scope_.get(i));
+ }
+ for (int i = 0; i < filePath_.size(); i++) {
+ output.writeBytes(5, filePath_.getByteString(i));
+ }
+ for (int i = 0; i < builderParameter_.size(); i++) {
+ output.writeMessage(6, builderParameter_.get(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, buildType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, globalSettings_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getProjectIdBytes());
+ }
+ for (int i = 0; i < scope_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, scope_.get(i));
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < filePath_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(filePath_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getFilePathList().size();
+ }
+ for (int i = 0; i < builderParameter_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(6, builderParameter_.get(i));
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ buildType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.REBUILD;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ globalSettings_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ projectId_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ scope_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ filePath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ builderParameter_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000020);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.buildType_ = buildType_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.globalSettings_ = globalSettings_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.projectId_ = projectId_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ scope_ = java.util.Collections.unmodifiableList(scope_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.scope_ = scope_;
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ filePath_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ filePath_);
+ bitField0_ = (bitField0_ & ~0x00000010);
+ }
+ result.filePath_ = filePath_;
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ builderParameter_ = java.util.Collections.unmodifiableList(builderParameter_);
+ bitField0_ = (bitField0_ & ~0x00000020);
+ }
+ result.builderParameter_ = builderParameter_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance()) return this;
+ if (other.hasBuildType()) {
+ setBuildType(other.getBuildType());
+ }
+ if (other.hasGlobalSettings()) {
+ mergeGlobalSettings(other.getGlobalSettings());
+ }
+ if (other.hasProjectId()) {
+ setProjectId(other.getProjectId());
+ }
+ if (!other.scope_.isEmpty()) {
+ if (scope_.isEmpty()) {
+ scope_ = other.scope_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureScopeIsMutable();
+ scope_.addAll(other.scope_);
+ }
+
+ }
+ if (!other.filePath_.isEmpty()) {
+ if (filePath_.isEmpty()) {
+ filePath_ = other.filePath_;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ } else {
+ ensureFilePathIsMutable();
+ filePath_.addAll(other.filePath_);
+ }
+
+ }
+ if (!other.builderParameter_.isEmpty()) {
+ if (builderParameter_.isEmpty()) {
+ builderParameter_ = other.builderParameter_;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ } else {
+ ensureBuilderParameterIsMutable();
+ builderParameter_.addAll(other.builderParameter_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasBuildType()) {
+
+ return false;
+ }
+ if (hasGlobalSettings()) {
+ if (!getGlobalSettings().isInitialized()) {
+
+ return false;
+ }
+ }
+ for (int i = 0; i < getScopeCount(); i++) {
+ if (!getScope(i).isInitialized()) {
+
+ return false;
+ }
+ }
+ for (int i = 0; i < getBuilderParameterCount(); i++) {
+ if (!getBuilderParameter(i).isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ buildType_ = value;
+ }
+ break;
+ }
+ case 18: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder();
+ if (hasGlobalSettings()) {
+ subBuilder.mergeFrom(getGlobalSettings());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setGlobalSettings(subBuilder.buildPartial());
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ projectId_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addScope(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ ensureFilePathIsMutable();
+ filePath_.add(input.readBytes());
+ break;
+ }
+ case 50: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addBuilderParameter(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.Type build_type = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type buildType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.REBUILD;
+ public boolean hasBuildType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type getBuildType() {
+ return buildType_;
+ }
+ public Builder setBuildType(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ buildType_ = value;
+
+ return this;
+ }
+ public Builder clearBuildType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ buildType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type.REBUILD;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.GlobalSettings global_settings = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globalSettings_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance();
+ public boolean hasGlobalSettings() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings getGlobalSettings() {
+ return globalSettings_;
+ }
+ public Builder setGlobalSettings(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ globalSettings_ = value;
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder setGlobalSettings(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.Builder builderForValue) {
+ globalSettings_ = builderForValue.build();
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder mergeGlobalSettings(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings value) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ globalSettings_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance()) {
+ globalSettings_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder(globalSettings_).mergeFrom(value).buildPartial();
+ } else {
+ globalSettings_ = value;
+ }
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder clearGlobalSettings() {
+ globalSettings_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ // optional string project_id = 3;
+ private java.lang.Object projectId_ = "";
+ public boolean hasProjectId() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getProjectId() {
+ java.lang.Object ref = projectId_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ projectId_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setProjectId(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ projectId_ = value;
+
+ return this;
+ }
+ public Builder clearProjectId() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ projectId_ = getDefaultInstance().getProjectId();
+
+ return this;
+ }
+ void setProjectId(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ projectId_ = value;
+
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope scope = 4;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> scope_ =
+ java.util.Collections.emptyList();
+ private void ensureScopeIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ scope_ = new java.util.ArrayList<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope>(scope_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> getScopeList() {
+ return java.util.Collections.unmodifiableList(scope_);
+ }
+ public int getScopeCount() {
+ return scope_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope getScope(int index) {
+ return scope_.get(index);
+ }
+ public Builder setScope(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureScopeIsMutable();
+ scope_.set(index, value);
+
+ return this;
+ }
+ public Builder setScope(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.Builder builderForValue) {
+ ensureScopeIsMutable();
+ scope_.set(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addScope(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureScopeIsMutable();
+ scope_.add(value);
+
+ return this;
+ }
+ public Builder addScope(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureScopeIsMutable();
+ scope_.add(index, value);
+
+ return this;
+ }
+ public Builder addScope(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.Builder builderForValue) {
+ ensureScopeIsMutable();
+ scope_.add(builderForValue.build());
+
+ return this;
+ }
+ public Builder addScope(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.Builder builderForValue) {
+ ensureScopeIsMutable();
+ scope_.add(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addAllScope(
+ java.lang.Iterable<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> values) {
+ ensureScopeIsMutable();
+ super.addAll(values, scope_);
+
+ return this;
+ }
+ public Builder clearScope() {
+ scope_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+
+ return this;
+ }
+ public Builder removeScope(int index) {
+ ensureScopeIsMutable();
+ scope_.remove(index);
+
+ return this;
+ }
+
+ // repeated string file_path = 5;
+ private com.google.protobuf.LazyStringList filePath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureFilePathIsMutable() {
+ if (!((bitField0_ & 0x00000010) == 0x00000010)) {
+ filePath_ = new com.google.protobuf.LazyStringArrayList(filePath_);
+ bitField0_ |= 0x00000010;
+ }
+ }
+ public java.util.List<String>
+ getFilePathList() {
+ return java.util.Collections.unmodifiableList(filePath_);
+ }
+ public int getFilePathCount() {
+ return filePath_.size();
+ }
+ public String getFilePath(int index) {
+ return filePath_.get(index);
+ }
+ public Builder setFilePath(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureFilePathIsMutable();
+ filePath_.set(index, value);
+
+ return this;
+ }
+ public Builder addFilePath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureFilePathIsMutable();
+ filePath_.add(value);
+
+ return this;
+ }
+ public Builder addAllFilePath(
+ java.lang.Iterable<String> values) {
+ ensureFilePathIsMutable();
+ super.addAll(values, filePath_);
+
+ return this;
+ }
+ public Builder clearFilePath() {
+ filePath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+
+ return this;
+ }
+ void addFilePath(com.google.protobuf.ByteString value) {
+ ensureFilePathIsMutable();
+ filePath_.add(value);
+
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.KeyValuePair builder_parameter = 6;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> builderParameter_ =
+ java.util.Collections.emptyList();
+ private void ensureBuilderParameterIsMutable() {
+ if (!((bitField0_ & 0x00000020) == 0x00000020)) {
+ builderParameter_ = new java.util.ArrayList<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair>(builderParameter_);
+ bitField0_ |= 0x00000020;
+ }
+ }
+
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> getBuilderParameterList() {
+ return java.util.Collections.unmodifiableList(builderParameter_);
+ }
+ public int getBuilderParameterCount() {
+ return builderParameter_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair getBuilderParameter(int index) {
+ return builderParameter_.get(index);
+ }
+ public Builder setBuilderParameter(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureBuilderParameterIsMutable();
+ builderParameter_.set(index, value);
+
+ return this;
+ }
+ public Builder setBuilderParameter(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensureBuilderParameterIsMutable();
+ builderParameter_.set(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addBuilderParameter(org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureBuilderParameterIsMutable();
+ builderParameter_.add(value);
+
+ return this;
+ }
+ public Builder addBuilderParameter(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureBuilderParameterIsMutable();
+ builderParameter_.add(index, value);
+
+ return this;
+ }
+ public Builder addBuilderParameter(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensureBuilderParameterIsMutable();
+ builderParameter_.add(builderForValue.build());
+
+ return this;
+ }
+ public Builder addBuilderParameter(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair.Builder builderForValue) {
+ ensureBuilderParameterIsMutable();
+ builderParameter_.add(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addAllBuilderParameter(
+ java.lang.Iterable<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.KeyValuePair> values) {
+ ensureBuilderParameterIsMutable();
+ super.addAll(values, builderParameter_);
+
+ return this;
+ }
+ public Builder clearBuilderParameter() {
+ builderParameter_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000020);
+
+ return this;
+ }
+ public Builder removeBuilderParameter(int index) {
+ ensureBuilderParameterIsMutable();
+ builderParameter_.remove(index);
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage)
+ }
+
+ static {
+ defaultInstance = new ParametersMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage)
+ }
+
+ public interface ConstantSearchResultOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string owner_class_name = 1;
+ boolean hasOwnerClassName();
+ String getOwnerClassName();
+
+ // required string field_name = 2;
+ boolean hasFieldName();
+ String getFieldName();
+
+ // required bool is_success = 3;
+ boolean hasIsSuccess();
+ boolean getIsSuccess();
+
+ // repeated string path = 4;
+ java.util.List<String> getPathList();
+ int getPathCount();
+ String getPath(int index);
+ }
+ public static final class ConstantSearchResult extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ConstantSearchResultOrBuilder {
+ // Use ConstantSearchResult.newBuilder() to construct.
+ private ConstantSearchResult(Builder builder) {
+ super(builder);
+ }
+ private ConstantSearchResult(boolean noInit) {}
+
+ private static final ConstantSearchResult defaultInstance;
+ public static ConstantSearchResult getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ConstantSearchResult getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string owner_class_name = 1;
+ public static final int OWNER_CLASS_NAME_FIELD_NUMBER = 1;
+ private java.lang.Object ownerClassName_;
+ public boolean hasOwnerClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOwnerClassName() {
+ java.lang.Object ref = ownerClassName_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ ownerClassName_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getOwnerClassNameBytes() {
+ java.lang.Object ref = ownerClassName_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ ownerClassName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string field_name = 2;
+ public static final int FIELD_NAME_FIELD_NUMBER = 2;
+ private java.lang.Object fieldName_;
+ public boolean hasFieldName() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFieldName() {
+ java.lang.Object ref = fieldName_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ fieldName_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getFieldNameBytes() {
+ java.lang.Object ref = fieldName_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ fieldName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required bool is_success = 3;
+ public static final int IS_SUCCESS_FIELD_NUMBER = 3;
+ private boolean isSuccess_;
+ public boolean hasIsSuccess() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public boolean getIsSuccess() {
+ return isSuccess_;
+ }
+
+ // repeated string path = 4;
+ public static final int PATH_FIELD_NUMBER = 4;
+ private com.google.protobuf.LazyStringList path_;
+ public java.util.List<String>
+ getPathList() {
+ return path_;
+ }
+ public int getPathCount() {
+ return path_.size();
+ }
+ public String getPath(int index) {
+ return path_.get(index);
+ }
+
+ private void initFields() {
+ ownerClassName_ = "";
+ fieldName_ = "";
+ isSuccess_ = false;
+ path_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasOwnerClassName()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasFieldName()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasIsSuccess()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getOwnerClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getFieldNameBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBool(3, isSuccess_);
+ }
+ for (int i = 0; i < path_.size(); i++) {
+ output.writeBytes(4, path_.getByteString(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getOwnerClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getFieldNameBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(3, isSuccess_);
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < path_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(path_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getPathList().size();
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResultOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ ownerClassName_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ fieldName_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ isSuccess_ = false;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ path_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.ownerClassName_ = ownerClassName_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.fieldName_ = fieldName_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.isSuccess_ = isSuccess_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ path_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ path_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.path_ = path_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance()) return this;
+ if (other.hasOwnerClassName()) {
+ setOwnerClassName(other.getOwnerClassName());
+ }
+ if (other.hasFieldName()) {
+ setFieldName(other.getFieldName());
+ }
+ if (other.hasIsSuccess()) {
+ setIsSuccess(other.getIsSuccess());
+ }
+ if (!other.path_.isEmpty()) {
+ if (path_.isEmpty()) {
+ path_ = other.path_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensurePathIsMutable();
+ path_.addAll(other.path_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasOwnerClassName()) {
+
+ return false;
+ }
+ if (!hasFieldName()) {
+
+ return false;
+ }
+ if (!hasIsSuccess()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ fieldName_ = input.readBytes();
+ break;
+ }
+ case 24: {
+ bitField0_ |= 0x00000004;
+ isSuccess_ = input.readBool();
+ break;
+ }
+ case 34: {
+ ensurePathIsMutable();
+ path_.add(input.readBytes());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string owner_class_name = 1;
+ private java.lang.Object ownerClassName_ = "";
+ public boolean hasOwnerClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOwnerClassName() {
+ java.lang.Object ref = ownerClassName_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ ownerClassName_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setOwnerClassName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = value;
+
+ return this;
+ }
+ public Builder clearOwnerClassName() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ ownerClassName_ = getDefaultInstance().getOwnerClassName();
+
+ return this;
+ }
+ void setOwnerClassName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = value;
+
+ }
+
+ // required string field_name = 2;
+ private java.lang.Object fieldName_ = "";
+ public boolean hasFieldName() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFieldName() {
+ java.lang.Object ref = fieldName_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ fieldName_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setFieldName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ fieldName_ = value;
+
+ return this;
+ }
+ public Builder clearFieldName() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ fieldName_ = getDefaultInstance().getFieldName();
+
+ return this;
+ }
+ void setFieldName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ fieldName_ = value;
+
+ }
+
+ // required bool is_success = 3;
+ private boolean isSuccess_ ;
+ public boolean hasIsSuccess() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public boolean getIsSuccess() {
+ return isSuccess_;
+ }
+ public Builder setIsSuccess(boolean value) {
+ bitField0_ |= 0x00000004;
+ isSuccess_ = value;
+
+ return this;
+ }
+ public Builder clearIsSuccess() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ isSuccess_ = false;
+
+ return this;
+ }
+
+ // repeated string path = 4;
+ private com.google.protobuf.LazyStringList path_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensurePathIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ path_ = new com.google.protobuf.LazyStringArrayList(path_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+ public java.util.List<String>
+ getPathList() {
+ return java.util.Collections.unmodifiableList(path_);
+ }
+ public int getPathCount() {
+ return path_.size();
+ }
+ public String getPath(int index) {
+ return path_.get(index);
+ }
+ public Builder setPath(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePathIsMutable();
+ path_.set(index, value);
+
+ return this;
+ }
+ public Builder addPath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePathIsMutable();
+ path_.add(value);
+
+ return this;
+ }
+ public Builder addAllPath(
+ java.lang.Iterable<String> values) {
+ ensurePathIsMutable();
+ super.addAll(values, path_);
+
+ return this;
+ }
+ public Builder clearPath() {
+ path_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+
+ return this;
+ }
+ void addPath(com.google.protobuf.ByteString value) {
+ ensurePathIsMutable();
+ path_.add(value);
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ConstantSearchResult)
+ }
+
+ static {
+ defaultInstance = new ConstantSearchResult(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage.ConstantSearchResult)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.Type type = 1;
+ public static final int TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type type_;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type getType() {
+ return type_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage params_message = 2;
+ public static final int PARAMS_MESSAGE_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage paramsMessage_;
+ public boolean hasParamsMessage() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage getParamsMessage() {
+ return paramsMessage_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.FSEvent fs_event = 3;
+ public static final int FS_EVENT_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent fsEvent_;
+ public boolean hasFsEvent() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent getFsEvent() {
+ return fsEvent_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ConstantSearchResult constant_search_result = 4;
+ public static final int CONSTANT_SEARCH_RESULT_FIELD_NUMBER = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult constantSearchResult_;
+ public boolean hasConstantSearchResult() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult getConstantSearchResult() {
+ return constantSearchResult_;
+ }
+
+ private void initFields() {
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type.BUILD_PARAMETERS;
+ paramsMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance();
+ fsEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance();
+ constantSearchResult_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasParamsMessage()) {
+ if (!getParamsMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasFsEvent()) {
+ if (!getFsEvent().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasConstantSearchResult()) {
+ if (!getConstantSearchResult().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, paramsMessage_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, fsEvent_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(4, constantSearchResult_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, paramsMessage_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, fsEvent_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, constantSearchResult_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type.BUILD_PARAMETERS;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ paramsMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ fsEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ constantSearchResult_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.type_ = type_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.paramsMessage_ = paramsMessage_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.fsEvent_ = fsEvent_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.constantSearchResult_ = constantSearchResult_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance()) return this;
+ if (other.hasType()) {
+ setType(other.getType());
+ }
+ if (other.hasParamsMessage()) {
+ mergeParamsMessage(other.getParamsMessage());
+ }
+ if (other.hasFsEvent()) {
+ mergeFsEvent(other.getFsEvent());
+ }
+ if (other.hasConstantSearchResult()) {
+ mergeConstantSearchResult(other.getConstantSearchResult());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasType()) {
+
+ return false;
+ }
+ if (hasParamsMessage()) {
+ if (!getParamsMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasFsEvent()) {
+ if (!getFsEvent().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasConstantSearchResult()) {
+ if (!getConstantSearchResult().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ type_ = value;
+ }
+ break;
+ }
+ case 18: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.newBuilder();
+ if (hasParamsMessage()) {
+ subBuilder.mergeFrom(getParamsMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setParamsMessage(subBuilder.buildPartial());
+ break;
+ }
+ case 26: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder();
+ if (hasFsEvent()) {
+ subBuilder.mergeFrom(getFsEvent());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setFsEvent(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder();
+ if (hasConstantSearchResult()) {
+ subBuilder.mergeFrom(getConstantSearchResult());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setConstantSearchResult(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.ControllerMessage.Type type = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type.BUILD_PARAMETERS;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type getType() {
+ return type_;
+ }
+ public Builder setType(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ type_ = value;
+
+ return this;
+ }
+ public Builder clearType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Type.BUILD_PARAMETERS;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ParametersMessage params_message = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage paramsMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance();
+ public boolean hasParamsMessage() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage getParamsMessage() {
+ return paramsMessage_;
+ }
+ public Builder setParamsMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ paramsMessage_ = value;
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder setParamsMessage(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Builder builderForValue) {
+ paramsMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder mergeParamsMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage value) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ paramsMessage_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance()) {
+ paramsMessage_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.newBuilder(paramsMessage_).mergeFrom(value).buildPartial();
+ } else {
+ paramsMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder clearParamsMessage() {
+ paramsMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.FSEvent fs_event = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent fsEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance();
+ public boolean hasFsEvent() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent getFsEvent() {
+ return fsEvent_;
+ }
+ public Builder setFsEvent(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ fsEvent_ = value;
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder setFsEvent(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.Builder builderForValue) {
+ fsEvent_ = builderForValue.build();
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder mergeFsEvent(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent value) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ fsEvent_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance()) {
+ fsEvent_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder(fsEvent_).mergeFrom(value).buildPartial();
+ } else {
+ fsEvent_ = value;
+ }
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder clearFsEvent() {
+ fsEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.FSEvent.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage.ConstantSearchResult constant_search_result = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult constantSearchResult_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance();
+ public boolean hasConstantSearchResult() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult getConstantSearchResult() {
+ return constantSearchResult_;
+ }
+ public Builder setConstantSearchResult(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ constantSearchResult_ = value;
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder setConstantSearchResult(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.Builder builderForValue) {
+ constantSearchResult_ = builderForValue.build();
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder mergeConstantSearchResult(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult value) {
+ if (((bitField0_ & 0x00000008) == 0x00000008) &&
+ constantSearchResult_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance()) {
+ constantSearchResult_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder(constantSearchResult_).mergeFrom(value).buildPartial();
+ } else {
+ constantSearchResult_ = value;
+ }
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder clearConstantSearchResult() {
+ constantSearchResult_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage)
+ }
+
+ static {
+ defaultInstance = new ControllerMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.ControllerMessage)
+ }
+
+ public interface BuilderMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.Type type = 1;
+ boolean hasType();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type getType();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent build_event = 2;
+ boolean hasBuildEvent();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent getBuildEvent();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage compile_message = 3;
+ boolean hasCompileMessage();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage getCompileMessage();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.ConstantSearchTask constant_search_task = 4;
+ boolean hasConstantSearchTask();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask getConstantSearchTask();
+ }
+ public static final class BuilderMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements BuilderMessageOrBuilder {
+ // Use BuilderMessage.newBuilder() to construct.
+ private BuilderMessage(Builder builder) {
+ super(builder);
+ }
+ private BuilderMessage(boolean noInit) {}
+
+ private static final BuilderMessage defaultInstance;
+ public static BuilderMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public BuilderMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ PARAM_REQUEST(0, 1),
+ BUILD_EVENT(1, 2),
+ COMPILE_MESSAGE(2, 3),
+ CONSTANT_SEARCH_TASK(3, 4),
+ ;
+
+ public static final int PARAM_REQUEST_VALUE = 1;
+ public static final int BUILD_EVENT_VALUE = 2;
+ public static final int COMPILE_MESSAGE_VALUE = 3;
+ public static final int CONSTANT_SEARCH_TASK_VALUE = 4;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return PARAM_REQUEST;
+ case 2: return BUILD_EVENT;
+ case 3: return COMPILE_MESSAGE;
+ case 4: return CONSTANT_SEARCH_TASK;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.BuilderMessage.Type)
+ }
+
+ public interface BuildEventOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Type event_type = 1;
+ boolean hasEventType();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type getEventType();
+
+ // optional string description = 2;
+ boolean hasDescription();
+ String getDescription();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Status completion_status = 3;
+ boolean hasCompletionStatus();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status getCompletionStatus();
+
+ // repeated .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.GeneratedFile generated_files = 4;
+ java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile>
+ getGeneratedFilesList();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile getGeneratedFiles(int index);
+ int getGeneratedFilesCount();
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.CustomBuilderMessage custom_builder_message = 5;
+ boolean hasCustomBuilderMessage();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage getCustomBuilderMessage();
+ }
+ public static final class BuildEvent extends
+ com.google.protobuf.GeneratedMessageLite
+ implements BuildEventOrBuilder {
+ // Use BuildEvent.newBuilder() to construct.
+ private BuildEvent(Builder builder) {
+ super(builder);
+ }
+ private BuildEvent(boolean noInit) {}
+
+ private static final BuildEvent defaultInstance;
+ public static BuildEvent getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public BuildEvent getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ BUILD_COMPLETED(0, 1),
+ FILES_GENERATED(1, 2),
+ CUSTOM_BUILDER_MESSAGE(2, 3),
+ ;
+
+ public static final int BUILD_COMPLETED_VALUE = 1;
+ public static final int FILES_GENERATED_VALUE = 2;
+ public static final int CUSTOM_BUILDER_MESSAGE_VALUE = 3;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return BUILD_COMPLETED;
+ case 2: return FILES_GENERATED;
+ case 3: return CUSTOM_BUILDER_MESSAGE;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Type)
+ }
+
+ public enum Status
+ implements com.google.protobuf.Internal.EnumLite {
+ CANCELED(0, 1),
+ ERRORS(1, 2),
+ SUCCESS(2, 3),
+ UP_TO_DATE(3, 4),
+ ;
+
+ public static final int CANCELED_VALUE = 1;
+ public static final int ERRORS_VALUE = 2;
+ public static final int SUCCESS_VALUE = 3;
+ public static final int UP_TO_DATE_VALUE = 4;
+
+
+ public final int getNumber() { return value; }
+
+ public static Status valueOf(int value) {
+ switch (value) {
+ case 1: return CANCELED;
+ case 2: return ERRORS;
+ case 3: return SUCCESS;
+ case 4: return UP_TO_DATE;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Status>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Status>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Status>() {
+ public Status findValueByNumber(int number) {
+ return Status.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Status(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Status)
+ }
+
+ public interface GeneratedFileOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string output_root = 1;
+ boolean hasOutputRoot();
+ String getOutputRoot();
+
+ // required string relative_path = 2;
+ boolean hasRelativePath();
+ String getRelativePath();
+ }
+ public static final class GeneratedFile extends
+ com.google.protobuf.GeneratedMessageLite
+ implements GeneratedFileOrBuilder {
+ // Use GeneratedFile.newBuilder() to construct.
+ private GeneratedFile(Builder builder) {
+ super(builder);
+ }
+ private GeneratedFile(boolean noInit) {}
+
+ private static final GeneratedFile defaultInstance;
+ public static GeneratedFile getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public GeneratedFile getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string output_root = 1;
+ public static final int OUTPUT_ROOT_FIELD_NUMBER = 1;
+ private java.lang.Object outputRoot_;
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ outputRoot_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getOutputRootBytes() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ outputRoot_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string relative_path = 2;
+ public static final int RELATIVE_PATH_FIELD_NUMBER = 2;
+ private java.lang.Object relativePath_;
+ public boolean hasRelativePath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getRelativePath() {
+ java.lang.Object ref = relativePath_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ relativePath_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getRelativePathBytes() {
+ java.lang.Object ref = relativePath_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ relativePath_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ outputRoot_ = "";
+ relativePath_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasOutputRoot()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasRelativePath()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getOutputRootBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getRelativePathBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getOutputRootBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getRelativePathBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFileOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ outputRoot_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ relativePath_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.outputRoot_ = outputRoot_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.relativePath_ = relativePath_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.getDefaultInstance()) return this;
+ if (other.hasOutputRoot()) {
+ setOutputRoot(other.getOutputRoot());
+ }
+ if (other.hasRelativePath()) {
+ setRelativePath(other.getRelativePath());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasOutputRoot()) {
+
+ return false;
+ }
+ if (!hasRelativePath()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ outputRoot_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ relativePath_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string output_root = 1;
+ private java.lang.Object outputRoot_ = "";
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ outputRoot_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setOutputRoot(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ outputRoot_ = value;
+
+ return this;
+ }
+ public Builder clearOutputRoot() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ outputRoot_ = getDefaultInstance().getOutputRoot();
+
+ return this;
+ }
+ void setOutputRoot(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ outputRoot_ = value;
+
+ }
+
+ // required string relative_path = 2;
+ private java.lang.Object relativePath_ = "";
+ public boolean hasRelativePath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getRelativePath() {
+ java.lang.Object ref = relativePath_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ relativePath_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setRelativePath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ relativePath_ = value;
+
+ return this;
+ }
+ public Builder clearRelativePath() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ relativePath_ = getDefaultInstance().getRelativePath();
+
+ return this;
+ }
+ void setRelativePath(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ relativePath_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.GeneratedFile)
+ }
+
+ static {
+ defaultInstance = new GeneratedFile(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.GeneratedFile)
+ }
+
+ public interface CustomBuilderMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string builder_id = 1;
+ boolean hasBuilderId();
+ String getBuilderId();
+
+ // required string message_type = 2;
+ boolean hasMessageType();
+ String getMessageType();
+
+ // required string message_text = 3;
+ boolean hasMessageText();
+ String getMessageText();
+ }
+ public static final class CustomBuilderMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements CustomBuilderMessageOrBuilder {
+ // Use CustomBuilderMessage.newBuilder() to construct.
+ private CustomBuilderMessage(Builder builder) {
+ super(builder);
+ }
+ private CustomBuilderMessage(boolean noInit) {}
+
+ private static final CustomBuilderMessage defaultInstance;
+ public static CustomBuilderMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public CustomBuilderMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string builder_id = 1;
+ public static final int BUILDER_ID_FIELD_NUMBER = 1;
+ private java.lang.Object builderId_;
+ public boolean hasBuilderId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getBuilderId() {
+ java.lang.Object ref = builderId_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ builderId_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getBuilderIdBytes() {
+ java.lang.Object ref = builderId_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ builderId_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string message_type = 2;
+ public static final int MESSAGE_TYPE_FIELD_NUMBER = 2;
+ private java.lang.Object messageType_;
+ public boolean hasMessageType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getMessageType() {
+ java.lang.Object ref = messageType_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ messageType_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getMessageTypeBytes() {
+ java.lang.Object ref = messageType_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ messageType_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string message_text = 3;
+ public static final int MESSAGE_TEXT_FIELD_NUMBER = 3;
+ private java.lang.Object messageText_;
+ public boolean hasMessageText() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getMessageText() {
+ java.lang.Object ref = messageText_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ messageText_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getMessageTextBytes() {
+ java.lang.Object ref = messageText_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ messageText_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ builderId_ = "";
+ messageType_ = "";
+ messageText_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasBuilderId()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasMessageType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasMessageText()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getBuilderIdBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getMessageTypeBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getMessageTextBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getBuilderIdBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getMessageTypeBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getMessageTextBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ builderId_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ messageType_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ messageText_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.builderId_ = builderId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.messageType_ = messageType_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.messageText_ = messageText_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance()) return this;
+ if (other.hasBuilderId()) {
+ setBuilderId(other.getBuilderId());
+ }
+ if (other.hasMessageType()) {
+ setMessageType(other.getMessageType());
+ }
+ if (other.hasMessageText()) {
+ setMessageText(other.getMessageText());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasBuilderId()) {
+
+ return false;
+ }
+ if (!hasMessageType()) {
+
+ return false;
+ }
+ if (!hasMessageText()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ builderId_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ messageType_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ messageText_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string builder_id = 1;
+ private java.lang.Object builderId_ = "";
+ public boolean hasBuilderId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getBuilderId() {
+ java.lang.Object ref = builderId_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ builderId_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setBuilderId(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ builderId_ = value;
+
+ return this;
+ }
+ public Builder clearBuilderId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ builderId_ = getDefaultInstance().getBuilderId();
+
+ return this;
+ }
+ void setBuilderId(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ builderId_ = value;
+
+ }
+
+ // required string message_type = 2;
+ private java.lang.Object messageType_ = "";
+ public boolean hasMessageType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getMessageType() {
+ java.lang.Object ref = messageType_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ messageType_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setMessageType(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ messageType_ = value;
+
+ return this;
+ }
+ public Builder clearMessageType() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ messageType_ = getDefaultInstance().getMessageType();
+
+ return this;
+ }
+ void setMessageType(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ messageType_ = value;
+
+ }
+
+ // required string message_text = 3;
+ private java.lang.Object messageText_ = "";
+ public boolean hasMessageText() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getMessageText() {
+ java.lang.Object ref = messageText_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ messageText_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setMessageText(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ messageText_ = value;
+
+ return this;
+ }
+ public Builder clearMessageText() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ messageText_ = getDefaultInstance().getMessageText();
+
+ return this;
+ }
+ void setMessageText(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ messageText_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.CustomBuilderMessage)
+ }
+
+ static {
+ defaultInstance = new CustomBuilderMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.CustomBuilderMessage)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Type event_type = 1;
+ public static final int EVENT_TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type eventType_;
+ public boolean hasEventType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type getEventType() {
+ return eventType_;
+ }
+
+ // optional string description = 2;
+ public static final int DESCRIPTION_FIELD_NUMBER = 2;
+ private java.lang.Object description_;
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ description_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getDescriptionBytes() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ description_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Status completion_status = 3;
+ public static final int COMPLETION_STATUS_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status completionStatus_;
+ public boolean hasCompletionStatus() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status getCompletionStatus() {
+ return completionStatus_;
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.GeneratedFile generated_files = 4;
+ public static final int GENERATED_FILES_FIELD_NUMBER = 4;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile> generatedFiles_;
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile> getGeneratedFilesList() {
+ return generatedFiles_;
+ }
+ public java.util.List<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFileOrBuilder>
+ getGeneratedFilesOrBuilderList() {
+ return generatedFiles_;
+ }
+ public int getGeneratedFilesCount() {
+ return generatedFiles_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile getGeneratedFiles(int index) {
+ return generatedFiles_.get(index);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFileOrBuilder getGeneratedFilesOrBuilder(
+ int index) {
+ return generatedFiles_.get(index);
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.CustomBuilderMessage custom_builder_message = 5;
+ public static final int CUSTOM_BUILDER_MESSAGE_FIELD_NUMBER = 5;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage customBuilderMessage_;
+ public boolean hasCustomBuilderMessage() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage getCustomBuilderMessage() {
+ return customBuilderMessage_;
+ }
+
+ private void initFields() {
+ eventType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type.BUILD_COMPLETED;
+ description_ = "";
+ completionStatus_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED;
+ generatedFiles_ = java.util.Collections.emptyList();
+ customBuilderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasEventType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ for (int i = 0; i < getGeneratedFilesCount(); i++) {
+ if (!getGeneratedFiles(i).isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasCustomBuilderMessage()) {
+ if (!getCustomBuilderMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, eventType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeEnum(3, completionStatus_.getNumber());
+ }
+ for (int i = 0; i < generatedFiles_.size(); i++) {
+ output.writeMessage(4, generatedFiles_.get(i));
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(5, customBuilderMessage_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, eventType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(3, completionStatus_.getNumber());
+ }
+ for (int i = 0; i < generatedFiles_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, generatedFiles_.get(i));
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(5, customBuilderMessage_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEventOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ eventType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type.BUILD_COMPLETED;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ description_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ completionStatus_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ generatedFiles_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ customBuilderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.eventType_ = eventType_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.description_ = description_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.completionStatus_ = completionStatus_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ generatedFiles_ = java.util.Collections.unmodifiableList(generatedFiles_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.generatedFiles_ = generatedFiles_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.customBuilderMessage_ = customBuilderMessage_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance()) return this;
+ if (other.hasEventType()) {
+ setEventType(other.getEventType());
+ }
+ if (other.hasDescription()) {
+ setDescription(other.getDescription());
+ }
+ if (other.hasCompletionStatus()) {
+ setCompletionStatus(other.getCompletionStatus());
+ }
+ if (!other.generatedFiles_.isEmpty()) {
+ if (generatedFiles_.isEmpty()) {
+ generatedFiles_ = other.generatedFiles_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.addAll(other.generatedFiles_);
+ }
+
+ }
+ if (other.hasCustomBuilderMessage()) {
+ mergeCustomBuilderMessage(other.getCustomBuilderMessage());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasEventType()) {
+
+ return false;
+ }
+ for (int i = 0; i < getGeneratedFilesCount(); i++) {
+ if (!getGeneratedFiles(i).isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasCustomBuilderMessage()) {
+ if (!getCustomBuilderMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ eventType_ = value;
+ }
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ description_ = input.readBytes();
+ break;
+ }
+ case 24: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000004;
+ completionStatus_ = value;
+ }
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addGeneratedFiles(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.newBuilder();
+ if (hasCustomBuilderMessage()) {
+ subBuilder.mergeFrom(getCustomBuilderMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setCustomBuilderMessage(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Type event_type = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type eventType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type.BUILD_COMPLETED;
+ public boolean hasEventType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type getEventType() {
+ return eventType_;
+ }
+ public Builder setEventType(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ eventType_ = value;
+
+ return this;
+ }
+ public Builder clearEventType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ eventType_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type.BUILD_COMPLETED;
+
+ return this;
+ }
+
+ // optional string description = 2;
+ private java.lang.Object description_ = "";
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ description_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setDescription(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ return this;
+ }
+ public Builder clearDescription() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ description_ = getDefaultInstance().getDescription();
+
+ return this;
+ }
+ void setDescription(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.Status completion_status = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status completionStatus_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED;
+ public boolean hasCompletionStatus() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status getCompletionStatus() {
+ return completionStatus_;
+ }
+ public Builder setCompletionStatus(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ completionStatus_ = value;
+
+ return this;
+ }
+ public Builder clearCompletionStatus() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ completionStatus_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED;
+
+ return this;
+ }
+
+ // repeated .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.GeneratedFile generated_files = 4;
+ private java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile> generatedFiles_ =
+ java.util.Collections.emptyList();
+ private void ensureGeneratedFilesIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ generatedFiles_ = new java.util.ArrayList<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile>(generatedFiles_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+
+ public java.util.List<org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile> getGeneratedFilesList() {
+ return java.util.Collections.unmodifiableList(generatedFiles_);
+ }
+ public int getGeneratedFilesCount() {
+ return generatedFiles_.size();
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile getGeneratedFiles(int index) {
+ return generatedFiles_.get(index);
+ }
+ public Builder setGeneratedFiles(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.set(index, value);
+
+ return this;
+ }
+ public Builder setGeneratedFiles(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.Builder builderForValue) {
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.set(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addGeneratedFiles(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.add(value);
+
+ return this;
+ }
+ public Builder addGeneratedFiles(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.add(index, value);
+
+ return this;
+ }
+ public Builder addGeneratedFiles(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.Builder builderForValue) {
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.add(builderForValue.build());
+
+ return this;
+ }
+ public Builder addGeneratedFiles(
+ int index, org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile.Builder builderForValue) {
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.add(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addAllGeneratedFiles(
+ java.lang.Iterable<? extends org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.GeneratedFile> values) {
+ ensureGeneratedFilesIsMutable();
+ super.addAll(values, generatedFiles_);
+
+ return this;
+ }
+ public Builder clearGeneratedFiles() {
+ generatedFiles_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+
+ return this;
+ }
+ public Builder removeGeneratedFiles(int index) {
+ ensureGeneratedFilesIsMutable();
+ generatedFiles_.remove(index);
+
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent.CustomBuilderMessage custom_builder_message = 5;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage customBuilderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance();
+ public boolean hasCustomBuilderMessage() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage getCustomBuilderMessage() {
+ return customBuilderMessage_;
+ }
+ public Builder setCustomBuilderMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ customBuilderMessage_ = value;
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder setCustomBuilderMessage(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.Builder builderForValue) {
+ customBuilderMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder mergeCustomBuilderMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage value) {
+ if (((bitField0_ & 0x00000010) == 0x00000010) &&
+ customBuilderMessage_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance()) {
+ customBuilderMessage_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.newBuilder(customBuilderMessage_).mergeFrom(value).buildPartial();
+ } else {
+ customBuilderMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder clearCustomBuilderMessage() {
+ customBuilderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.CustomBuilderMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent)
+ }
+
+ static {
+ defaultInstance = new BuildEvent(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent)
+ }
+
+ public interface CompileMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage.Kind kind = 1;
+ boolean hasKind();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind getKind();
+
+ // optional string text = 2;
+ boolean hasText();
+ String getText();
+
+ // optional string source_file_path = 3;
+ boolean hasSourceFilePath();
+ String getSourceFilePath();
+
+ // optional uint64 problem_begin_offset = 4;
+ boolean hasProblemBeginOffset();
+ long getProblemBeginOffset();
+
+ // optional uint64 problem_end_offset = 5;
+ boolean hasProblemEndOffset();
+ long getProblemEndOffset();
+
+ // optional uint64 problem_location_offset = 6;
+ boolean hasProblemLocationOffset();
+ long getProblemLocationOffset();
+
+ // optional uint64 line = 7;
+ boolean hasLine();
+ long getLine();
+
+ // optional uint64 column = 8;
+ boolean hasColumn();
+ long getColumn();
+
+ // optional float done = 9;
+ boolean hasDone();
+ float getDone();
+ }
+ public static final class CompileMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements CompileMessageOrBuilder {
+ // Use CompileMessage.newBuilder() to construct.
+ private CompileMessage(Builder builder) {
+ super(builder);
+ }
+ private CompileMessage(boolean noInit) {}
+
+ private static final CompileMessage defaultInstance;
+ public static CompileMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public CompileMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Kind
+ implements com.google.protobuf.Internal.EnumLite {
+ ERROR(0, 1),
+ WARNING(1, 2),
+ INFO(2, 3),
+ PROGRESS(3, 4),
+ ;
+
+ public static final int ERROR_VALUE = 1;
+ public static final int WARNING_VALUE = 2;
+ public static final int INFO_VALUE = 3;
+ public static final int PROGRESS_VALUE = 4;
+
+
+ public final int getNumber() { return value; }
+
+ public static Kind valueOf(int value) {
+ switch (value) {
+ case 1: return ERROR;
+ case 2: return WARNING;
+ case 3: return INFO;
+ case 4: return PROGRESS;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Kind>() {
+ public Kind findValueByNumber(int number) {
+ return Kind.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Kind(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage.Kind)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage.Kind kind = 1;
+ public static final int KIND_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind kind_;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind getKind() {
+ return kind_;
+ }
+
+ // optional string text = 2;
+ public static final int TEXT_FIELD_NUMBER = 2;
+ private java.lang.Object text_;
+ public boolean hasText() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getText() {
+ java.lang.Object ref = text_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ text_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getTextBytes() {
+ java.lang.Object ref = text_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ text_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string source_file_path = 3;
+ public static final int SOURCE_FILE_PATH_FIELD_NUMBER = 3;
+ private java.lang.Object sourceFilePath_;
+ public boolean hasSourceFilePath() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getSourceFilePath() {
+ java.lang.Object ref = sourceFilePath_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ sourceFilePath_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getSourceFilePathBytes() {
+ java.lang.Object ref = sourceFilePath_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ sourceFilePath_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional uint64 problem_begin_offset = 4;
+ public static final int PROBLEM_BEGIN_OFFSET_FIELD_NUMBER = 4;
+ private long problemBeginOffset_;
+ public boolean hasProblemBeginOffset() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public long getProblemBeginOffset() {
+ return problemBeginOffset_;
+ }
+
+ // optional uint64 problem_end_offset = 5;
+ public static final int PROBLEM_END_OFFSET_FIELD_NUMBER = 5;
+ private long problemEndOffset_;
+ public boolean hasProblemEndOffset() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public long getProblemEndOffset() {
+ return problemEndOffset_;
+ }
+
+ // optional uint64 problem_location_offset = 6;
+ public static final int PROBLEM_LOCATION_OFFSET_FIELD_NUMBER = 6;
+ private long problemLocationOffset_;
+ public boolean hasProblemLocationOffset() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public long getProblemLocationOffset() {
+ return problemLocationOffset_;
+ }
+
+ // optional uint64 line = 7;
+ public static final int LINE_FIELD_NUMBER = 7;
+ private long line_;
+ public boolean hasLine() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public long getLine() {
+ return line_;
+ }
+
+ // optional uint64 column = 8;
+ public static final int COLUMN_FIELD_NUMBER = 8;
+ private long column_;
+ public boolean hasColumn() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ public long getColumn() {
+ return column_;
+ }
+
+ // optional float done = 9;
+ public static final int DONE_FIELD_NUMBER = 9;
+ private float done_;
+ public boolean hasDone() {
+ return ((bitField0_ & 0x00000100) == 0x00000100);
+ }
+ public float getDone() {
+ return done_;
+ }
+
+ private void initFields() {
+ kind_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.ERROR;
+ text_ = "";
+ sourceFilePath_ = "";
+ problemBeginOffset_ = 0L;
+ problemEndOffset_ = 0L;
+ problemLocationOffset_ = 0L;
+ line_ = 0L;
+ column_ = 0L;
+ done_ = 0F;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasKind()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getTextBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getSourceFilePathBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeUInt64(4, problemBeginOffset_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeUInt64(5, problemEndOffset_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeUInt64(6, problemLocationOffset_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output.writeUInt64(7, line_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ output.writeUInt64(8, column_);
+ }
+ if (((bitField0_ & 0x00000100) == 0x00000100)) {
+ output.writeFloat(9, done_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getTextBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getSourceFilePathBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(4, problemBeginOffset_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(5, problemEndOffset_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(6, problemLocationOffset_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(7, line_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(8, column_);
+ }
+ if (((bitField0_ & 0x00000100) == 0x00000100)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeFloatSize(9, done_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ kind_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.ERROR;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ text_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ sourceFilePath_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ problemBeginOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ problemEndOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ problemLocationOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ line_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ column_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000080);
+ done_ = 0F;
+ bitField0_ = (bitField0_ & ~0x00000100);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.kind_ = kind_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.text_ = text_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.sourceFilePath_ = sourceFilePath_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.problemBeginOffset_ = problemBeginOffset_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.problemEndOffset_ = problemEndOffset_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.problemLocationOffset_ = problemLocationOffset_;
+ if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+ to_bitField0_ |= 0x00000040;
+ }
+ result.line_ = line_;
+ if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+ to_bitField0_ |= 0x00000080;
+ }
+ result.column_ = column_;
+ if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+ to_bitField0_ |= 0x00000100;
+ }
+ result.done_ = done_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance()) return this;
+ if (other.hasKind()) {
+ setKind(other.getKind());
+ }
+ if (other.hasText()) {
+ setText(other.getText());
+ }
+ if (other.hasSourceFilePath()) {
+ setSourceFilePath(other.getSourceFilePath());
+ }
+ if (other.hasProblemBeginOffset()) {
+ setProblemBeginOffset(other.getProblemBeginOffset());
+ }
+ if (other.hasProblemEndOffset()) {
+ setProblemEndOffset(other.getProblemEndOffset());
+ }
+ if (other.hasProblemLocationOffset()) {
+ setProblemLocationOffset(other.getProblemLocationOffset());
+ }
+ if (other.hasLine()) {
+ setLine(other.getLine());
+ }
+ if (other.hasColumn()) {
+ setColumn(other.getColumn());
+ }
+ if (other.hasDone()) {
+ setDone(other.getDone());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasKind()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+ }
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ text_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ sourceFilePath_ = input.readBytes();
+ break;
+ }
+ case 32: {
+ bitField0_ |= 0x00000008;
+ problemBeginOffset_ = input.readUInt64();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ problemEndOffset_ = input.readUInt64();
+ break;
+ }
+ case 48: {
+ bitField0_ |= 0x00000020;
+ problemLocationOffset_ = input.readUInt64();
+ break;
+ }
+ case 56: {
+ bitField0_ |= 0x00000040;
+ line_ = input.readUInt64();
+ break;
+ }
+ case 64: {
+ bitField0_ |= 0x00000080;
+ column_ = input.readUInt64();
+ break;
+ }
+ case 77: {
+ bitField0_ |= 0x00000100;
+ done_ = input.readFloat();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage.Kind kind = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind kind_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.ERROR;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind getKind() {
+ return kind_;
+ }
+ public Builder setKind(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+
+ return this;
+ }
+ public Builder clearKind() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ kind_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.ERROR;
+
+ return this;
+ }
+
+ // optional string text = 2;
+ private java.lang.Object text_ = "";
+ public boolean hasText() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getText() {
+ java.lang.Object ref = text_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ text_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setText(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ text_ = value;
+
+ return this;
+ }
+ public Builder clearText() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ text_ = getDefaultInstance().getText();
+
+ return this;
+ }
+ void setText(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ text_ = value;
+
+ }
+
+ // optional string source_file_path = 3;
+ private java.lang.Object sourceFilePath_ = "";
+ public boolean hasSourceFilePath() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getSourceFilePath() {
+ java.lang.Object ref = sourceFilePath_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ sourceFilePath_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setSourceFilePath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ sourceFilePath_ = value;
+
+ return this;
+ }
+ public Builder clearSourceFilePath() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ sourceFilePath_ = getDefaultInstance().getSourceFilePath();
+
+ return this;
+ }
+ void setSourceFilePath(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ sourceFilePath_ = value;
+
+ }
+
+ // optional uint64 problem_begin_offset = 4;
+ private long problemBeginOffset_ ;
+ public boolean hasProblemBeginOffset() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public long getProblemBeginOffset() {
+ return problemBeginOffset_;
+ }
+ public Builder setProblemBeginOffset(long value) {
+ bitField0_ |= 0x00000008;
+ problemBeginOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemBeginOffset() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ problemBeginOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 problem_end_offset = 5;
+ private long problemEndOffset_ ;
+ public boolean hasProblemEndOffset() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public long getProblemEndOffset() {
+ return problemEndOffset_;
+ }
+ public Builder setProblemEndOffset(long value) {
+ bitField0_ |= 0x00000010;
+ problemEndOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemEndOffset() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ problemEndOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 problem_location_offset = 6;
+ private long problemLocationOffset_ ;
+ public boolean hasProblemLocationOffset() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public long getProblemLocationOffset() {
+ return problemLocationOffset_;
+ }
+ public Builder setProblemLocationOffset(long value) {
+ bitField0_ |= 0x00000020;
+ problemLocationOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemLocationOffset() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ problemLocationOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 line = 7;
+ private long line_ ;
+ public boolean hasLine() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public long getLine() {
+ return line_;
+ }
+ public Builder setLine(long value) {
+ bitField0_ |= 0x00000040;
+ line_ = value;
+
+ return this;
+ }
+ public Builder clearLine() {
+ bitField0_ = (bitField0_ & ~0x00000040);
+ line_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 column = 8;
+ private long column_ ;
+ public boolean hasColumn() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ public long getColumn() {
+ return column_;
+ }
+ public Builder setColumn(long value) {
+ bitField0_ |= 0x00000080;
+ column_ = value;
+
+ return this;
+ }
+ public Builder clearColumn() {
+ bitField0_ = (bitField0_ & ~0x00000080);
+ column_ = 0L;
+
+ return this;
+ }
+
+ // optional float done = 9;
+ private float done_ ;
+ public boolean hasDone() {
+ return ((bitField0_ & 0x00000100) == 0x00000100);
+ }
+ public float getDone() {
+ return done_;
+ }
+ public Builder setDone(float value) {
+ bitField0_ |= 0x00000100;
+ done_ = value;
+
+ return this;
+ }
+ public Builder clearDone() {
+ bitField0_ = (bitField0_ & ~0x00000100);
+ done_ = 0F;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage)
+ }
+
+ static {
+ defaultInstance = new CompileMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage)
+ }
+
+ public interface ConstantSearchTaskOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string owner_class_name = 1;
+ boolean hasOwnerClassName();
+ String getOwnerClassName();
+
+ // required string field_name = 2;
+ boolean hasFieldName();
+ String getFieldName();
+
+ // required int32 access_flags = 3;
+ boolean hasAccessFlags();
+ int getAccessFlags();
+
+ // optional bool is_access_changed = 4 [default = false];
+ boolean hasIsAccessChanged();
+ boolean getIsAccessChanged();
+
+ // optional bool is_field_removed = 5 [default = false];
+ boolean hasIsFieldRemoved();
+ boolean getIsFieldRemoved();
+ }
+ public static final class ConstantSearchTask extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ConstantSearchTaskOrBuilder {
+ // Use ConstantSearchTask.newBuilder() to construct.
+ private ConstantSearchTask(Builder builder) {
+ super(builder);
+ }
+ private ConstantSearchTask(boolean noInit) {}
+
+ private static final ConstantSearchTask defaultInstance;
+ public static ConstantSearchTask getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ConstantSearchTask getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string owner_class_name = 1;
+ public static final int OWNER_CLASS_NAME_FIELD_NUMBER = 1;
+ private java.lang.Object ownerClassName_;
+ public boolean hasOwnerClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOwnerClassName() {
+ java.lang.Object ref = ownerClassName_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ ownerClassName_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getOwnerClassNameBytes() {
+ java.lang.Object ref = ownerClassName_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ ownerClassName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required string field_name = 2;
+ public static final int FIELD_NAME_FIELD_NUMBER = 2;
+ private java.lang.Object fieldName_;
+ public boolean hasFieldName() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFieldName() {
+ java.lang.Object ref = fieldName_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ fieldName_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getFieldNameBytes() {
+ java.lang.Object ref = fieldName_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ fieldName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // required int32 access_flags = 3;
+ public static final int ACCESS_FLAGS_FIELD_NUMBER = 3;
+ private int accessFlags_;
+ public boolean hasAccessFlags() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public int getAccessFlags() {
+ return accessFlags_;
+ }
+
+ // optional bool is_access_changed = 4 [default = false];
+ public static final int IS_ACCESS_CHANGED_FIELD_NUMBER = 4;
+ private boolean isAccessChanged_;
+ public boolean hasIsAccessChanged() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public boolean getIsAccessChanged() {
+ return isAccessChanged_;
+ }
+
+ // optional bool is_field_removed = 5 [default = false];
+ public static final int IS_FIELD_REMOVED_FIELD_NUMBER = 5;
+ private boolean isFieldRemoved_;
+ public boolean hasIsFieldRemoved() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public boolean getIsFieldRemoved() {
+ return isFieldRemoved_;
+ }
+
+ private void initFields() {
+ ownerClassName_ = "";
+ fieldName_ = "";
+ accessFlags_ = 0;
+ isAccessChanged_ = false;
+ isFieldRemoved_ = false;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasOwnerClassName()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasFieldName()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasAccessFlags()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getOwnerClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getFieldNameBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeInt32(3, accessFlags_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBool(4, isAccessChanged_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBool(5, isFieldRemoved_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getOwnerClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getFieldNameBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(3, accessFlags_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(4, isAccessChanged_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(5, isFieldRemoved_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTaskOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ ownerClassName_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ fieldName_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ accessFlags_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ isAccessChanged_ = false;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ isFieldRemoved_ = false;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.ownerClassName_ = ownerClassName_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.fieldName_ = fieldName_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.accessFlags_ = accessFlags_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.isAccessChanged_ = isAccessChanged_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.isFieldRemoved_ = isFieldRemoved_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance()) return this;
+ if (other.hasOwnerClassName()) {
+ setOwnerClassName(other.getOwnerClassName());
+ }
+ if (other.hasFieldName()) {
+ setFieldName(other.getFieldName());
+ }
+ if (other.hasAccessFlags()) {
+ setAccessFlags(other.getAccessFlags());
+ }
+ if (other.hasIsAccessChanged()) {
+ setIsAccessChanged(other.getIsAccessChanged());
+ }
+ if (other.hasIsFieldRemoved()) {
+ setIsFieldRemoved(other.getIsFieldRemoved());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasOwnerClassName()) {
+
+ return false;
+ }
+ if (!hasFieldName()) {
+
+ return false;
+ }
+ if (!hasAccessFlags()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ fieldName_ = input.readBytes();
+ break;
+ }
+ case 24: {
+ bitField0_ |= 0x00000004;
+ accessFlags_ = input.readInt32();
+ break;
+ }
+ case 32: {
+ bitField0_ |= 0x00000008;
+ isAccessChanged_ = input.readBool();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ isFieldRemoved_ = input.readBool();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string owner_class_name = 1;
+ private java.lang.Object ownerClassName_ = "";
+ public boolean hasOwnerClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOwnerClassName() {
+ java.lang.Object ref = ownerClassName_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ ownerClassName_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setOwnerClassName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = value;
+
+ return this;
+ }
+ public Builder clearOwnerClassName() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ ownerClassName_ = getDefaultInstance().getOwnerClassName();
+
+ return this;
+ }
+ void setOwnerClassName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ ownerClassName_ = value;
+
+ }
+
+ // required string field_name = 2;
+ private java.lang.Object fieldName_ = "";
+ public boolean hasFieldName() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFieldName() {
+ java.lang.Object ref = fieldName_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ fieldName_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setFieldName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ fieldName_ = value;
+
+ return this;
+ }
+ public Builder clearFieldName() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ fieldName_ = getDefaultInstance().getFieldName();
+
+ return this;
+ }
+ void setFieldName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ fieldName_ = value;
+
+ }
+
+ // required int32 access_flags = 3;
+ private int accessFlags_ ;
+ public boolean hasAccessFlags() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public int getAccessFlags() {
+ return accessFlags_;
+ }
+ public Builder setAccessFlags(int value) {
+ bitField0_ |= 0x00000004;
+ accessFlags_ = value;
+
+ return this;
+ }
+ public Builder clearAccessFlags() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ accessFlags_ = 0;
+
+ return this;
+ }
+
+ // optional bool is_access_changed = 4 [default = false];
+ private boolean isAccessChanged_ ;
+ public boolean hasIsAccessChanged() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public boolean getIsAccessChanged() {
+ return isAccessChanged_;
+ }
+ public Builder setIsAccessChanged(boolean value) {
+ bitField0_ |= 0x00000008;
+ isAccessChanged_ = value;
+
+ return this;
+ }
+ public Builder clearIsAccessChanged() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ isAccessChanged_ = false;
+
+ return this;
+ }
+
+ // optional bool is_field_removed = 5 [default = false];
+ private boolean isFieldRemoved_ ;
+ public boolean hasIsFieldRemoved() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public boolean getIsFieldRemoved() {
+ return isFieldRemoved_;
+ }
+ public Builder setIsFieldRemoved(boolean value) {
+ bitField0_ |= 0x00000010;
+ isFieldRemoved_ = value;
+
+ return this;
+ }
+ public Builder clearIsFieldRemoved() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ isFieldRemoved_ = false;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage.ConstantSearchTask)
+ }
+
+ static {
+ defaultInstance = new ConstantSearchTask(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage.ConstantSearchTask)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.Type type = 1;
+ public static final int TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type type_;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type getType() {
+ return type_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent build_event = 2;
+ public static final int BUILD_EVENT_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent buildEvent_;
+ public boolean hasBuildEvent() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent getBuildEvent() {
+ return buildEvent_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage compile_message = 3;
+ public static final int COMPILE_MESSAGE_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage compileMessage_;
+ public boolean hasCompileMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage getCompileMessage() {
+ return compileMessage_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.ConstantSearchTask constant_search_task = 4;
+ public static final int CONSTANT_SEARCH_TASK_FIELD_NUMBER = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask constantSearchTask_;
+ public boolean hasConstantSearchTask() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask getConstantSearchTask() {
+ return constantSearchTask_;
+ }
+
+ private void initFields() {
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST;
+ buildEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance();
+ compileMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance();
+ constantSearchTask_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasBuildEvent()) {
+ if (!getBuildEvent().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasCompileMessage()) {
+ if (!getCompileMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasConstantSearchTask()) {
+ if (!getConstantSearchTask().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, buildEvent_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, compileMessage_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(4, constantSearchTask_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, buildEvent_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, compileMessage_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, constantSearchTask_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ buildEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ compileMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ constantSearchTask_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.type_ = type_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.buildEvent_ = buildEvent_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.compileMessage_ = compileMessage_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.constantSearchTask_ = constantSearchTask_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance()) return this;
+ if (other.hasType()) {
+ setType(other.getType());
+ }
+ if (other.hasBuildEvent()) {
+ mergeBuildEvent(other.getBuildEvent());
+ }
+ if (other.hasCompileMessage()) {
+ mergeCompileMessage(other.getCompileMessage());
+ }
+ if (other.hasConstantSearchTask()) {
+ mergeConstantSearchTask(other.getConstantSearchTask());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasType()) {
+
+ return false;
+ }
+ if (hasBuildEvent()) {
+ if (!getBuildEvent().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasCompileMessage()) {
+ if (!getCompileMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasConstantSearchTask()) {
+ if (!getConstantSearchTask().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ type_ = value;
+ }
+ break;
+ }
+ case 18: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.newBuilder();
+ if (hasBuildEvent()) {
+ subBuilder.mergeFrom(getBuildEvent());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setBuildEvent(subBuilder.buildPartial());
+ break;
+ }
+ case 26: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.newBuilder();
+ if (hasCompileMessage()) {
+ subBuilder.mergeFrom(getCompileMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setCompileMessage(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.newBuilder();
+ if (hasConstantSearchTask()) {
+ subBuilder.mergeFrom(getConstantSearchTask());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setConstantSearchTask(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.BuilderMessage.Type type = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type getType() {
+ return type_;
+ }
+ public Builder setType(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ type_ = value;
+
+ return this;
+ }
+ public Builder clearType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.BuildEvent build_event = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent buildEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance();
+ public boolean hasBuildEvent() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent getBuildEvent() {
+ return buildEvent_;
+ }
+ public Builder setBuildEvent(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ buildEvent_ = value;
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder setBuildEvent(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Builder builderForValue) {
+ buildEvent_ = builderForValue.build();
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder mergeBuildEvent(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent value) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ buildEvent_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance()) {
+ buildEvent_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.newBuilder(buildEvent_).mergeFrom(value).buildPartial();
+ } else {
+ buildEvent_ = value;
+ }
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder clearBuildEvent() {
+ buildEvent_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.CompileMessage compile_message = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage compileMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance();
+ public boolean hasCompileMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage getCompileMessage() {
+ return compileMessage_;
+ }
+ public Builder setCompileMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ compileMessage_ = value;
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder setCompileMessage(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Builder builderForValue) {
+ compileMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder mergeCompileMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage value) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ compileMessage_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance()) {
+ compileMessage_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.newBuilder(compileMessage_).mergeFrom(value).buildPartial();
+ } else {
+ compileMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder clearCompileMessage() {
+ compileMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage.ConstantSearchTask constant_search_task = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask constantSearchTask_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance();
+ public boolean hasConstantSearchTask() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask getConstantSearchTask() {
+ return constantSearchTask_;
+ }
+ public Builder setConstantSearchTask(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ constantSearchTask_ = value;
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder setConstantSearchTask(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.Builder builderForValue) {
+ constantSearchTask_ = builderForValue.build();
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder mergeConstantSearchTask(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask value) {
+ if (((bitField0_ & 0x00000008) == 0x00000008) &&
+ constantSearchTask_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance()) {
+ constantSearchTask_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.newBuilder(constantSearchTask_).mergeFrom(value).buildPartial();
+ } else {
+ constantSearchTask_ = value;
+ }
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder clearConstantSearchTask() {
+ constantSearchTask_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.BuilderMessage)
+ }
+
+ static {
+ defaultInstance = new BuilderMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.BuilderMessage)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.jpsservice.Message.UUID session_id = 1;
+ public static final int SESSION_ID_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID sessionId_;
+ public boolean hasSessionId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID getSessionId() {
+ return sessionId_;
+ }
+
+ // required .org.jetbrains.jpsservice.Message.Type type = 2;
+ public static final int TYPE_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type type_;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type getType() {
+ return type_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage controller_message = 3;
+ public static final int CONTROLLER_MESSAGE_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage controllerMessage_;
+ public boolean hasControllerMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage getControllerMessage() {
+ return controllerMessage_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage builder_message = 4;
+ public static final int BUILDER_MESSAGE_FIELD_NUMBER = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage builderMessage_;
+ public boolean hasBuilderMessage() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage getBuilderMessage() {
+ return builderMessage_;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.Failure failure = 5;
+ public static final int FAILURE_FIELD_NUMBER = 5;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure failure_;
+ public boolean hasFailure() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure getFailure() {
+ return failure_;
+ }
+
+ private void initFields() {
+ sessionId_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance();
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE;
+ controllerMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance();
+ builderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance();
+ failure_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasSessionId()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!getSessionId().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasControllerMessage()) {
+ if (!getControllerMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasBuilderMessage()) {
+ if (!getBuilderMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeMessage(1, sessionId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeEnum(2, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, controllerMessage_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(4, builderMessage_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeMessage(5, failure_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, sessionId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(2, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, controllerMessage_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, builderMessage_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(5, failure_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.api.CmdlineRemoteProto.Message parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.api.CmdlineRemoteProto.Message prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message, Builder>
+ implements org.jetbrains.jps.api.CmdlineRemoteProto.MessageOrBuilder {
+ // Construct using org.jetbrains.jps.api.CmdlineRemoteProto.Message.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ sessionId_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ controllerMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ builderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ failure_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message getDefaultInstanceForType() {
+ return org.jetbrains.jps.api.CmdlineRemoteProto.Message.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message build() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message buildPartial() {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message result = new org.jetbrains.jps.api.CmdlineRemoteProto.Message(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.sessionId_ = sessionId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.type_ = type_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.controllerMessage_ = controllerMessage_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.builderMessage_ = builderMessage_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.failure_ = failure_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.api.CmdlineRemoteProto.Message other) {
+ if (other == org.jetbrains.jps.api.CmdlineRemoteProto.Message.getDefaultInstance()) return this;
+ if (other.hasSessionId()) {
+ mergeSessionId(other.getSessionId());
+ }
+ if (other.hasType()) {
+ setType(other.getType());
+ }
+ if (other.hasControllerMessage()) {
+ mergeControllerMessage(other.getControllerMessage());
+ }
+ if (other.hasBuilderMessage()) {
+ mergeBuilderMessage(other.getBuilderMessage());
+ }
+ if (other.hasFailure()) {
+ mergeFailure(other.getFailure());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasSessionId()) {
+
+ return false;
+ }
+ if (!hasType()) {
+
+ return false;
+ }
+ if (!getSessionId().isInitialized()) {
+
+ return false;
+ }
+ if (hasControllerMessage()) {
+ if (!getControllerMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasBuilderMessage()) {
+ if (!getBuilderMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.newBuilder();
+ if (hasSessionId()) {
+ subBuilder.mergeFrom(getSessionId());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setSessionId(subBuilder.buildPartial());
+ break;
+ }
+ case 16: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type value = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000002;
+ type_ = value;
+ }
+ break;
+ }
+ case 26: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.newBuilder();
+ if (hasControllerMessage()) {
+ subBuilder.mergeFrom(getControllerMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setControllerMessage(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.newBuilder();
+ if (hasBuilderMessage()) {
+ subBuilder.mergeFrom(getBuilderMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setBuilderMessage(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.Builder subBuilder = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.newBuilder();
+ if (hasFailure()) {
+ subBuilder.mergeFrom(getFailure());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setFailure(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.jpsservice.Message.UUID session_id = 1;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID sessionId_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance();
+ public boolean hasSessionId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID getSessionId() {
+ return sessionId_;
+ }
+ public Builder setSessionId(org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ sessionId_ = value;
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder setSessionId(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.Builder builderForValue) {
+ sessionId_ = builderForValue.build();
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder mergeSessionId(org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID value) {
+ if (((bitField0_ & 0x00000001) == 0x00000001) &&
+ sessionId_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance()) {
+ sessionId_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.newBuilder(sessionId_).mergeFrom(value).buildPartial();
+ } else {
+ sessionId_ = value;
+ }
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder clearSessionId() {
+ sessionId_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.UUID.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000001);
+ return this;
+ }
+
+ // required .org.jetbrains.jpsservice.Message.Type type = 2;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE;
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type getType() {
+ return type_;
+ }
+ public Builder setType(org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ type_ = value;
+
+ return this;
+ }
+ public Builder clearType() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ type_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.ControllerMessage controller_message = 3;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage controllerMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance();
+ public boolean hasControllerMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage getControllerMessage() {
+ return controllerMessage_;
+ }
+ public Builder setControllerMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ controllerMessage_ = value;
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder setControllerMessage(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.Builder builderForValue) {
+ controllerMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder mergeControllerMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage value) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ controllerMessage_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance()) {
+ controllerMessage_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.newBuilder(controllerMessage_).mergeFrom(value).buildPartial();
+ } else {
+ controllerMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder clearControllerMessage() {
+ controllerMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.BuilderMessage builder_message = 4;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage builderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance();
+ public boolean hasBuilderMessage() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage getBuilderMessage() {
+ return builderMessage_;
+ }
+ public Builder setBuilderMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ builderMessage_ = value;
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder setBuilderMessage(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.Builder builderForValue) {
+ builderMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder mergeBuilderMessage(org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage value) {
+ if (((bitField0_ & 0x00000008) == 0x00000008) &&
+ builderMessage_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance()) {
+ builderMessage_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.newBuilder(builderMessage_).mergeFrom(value).buildPartial();
+ } else {
+ builderMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder clearBuilderMessage() {
+ builderMessage_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.BuilderMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ // optional .org.jetbrains.jpsservice.Message.Failure failure = 5;
+ private org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure failure_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance();
+ public boolean hasFailure() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure getFailure() {
+ return failure_;
+ }
+ public Builder setFailure(org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ failure_ = value;
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder setFailure(
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.Builder builderForValue) {
+ failure_ = builderForValue.build();
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder mergeFailure(org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure value) {
+ if (((bitField0_ & 0x00000010) == 0x00000010) &&
+ failure_ != org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance()) {
+ failure_ =
+ org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.newBuilder(failure_).mergeFrom(value).buildPartial();
+ } else {
+ failure_ = value;
+ }
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder clearFailure() {
+ failure_ = org.jetbrains.jps.api.CmdlineRemoteProto.Message.Failure.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message)
+ }
+
+ static {
+ defaultInstance = new Message(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message)
+ }
+
+
+ static {
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java
new file mode 100644
index 000000000000..d772b3c6c1b4
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/24/12
+ */
+public interface GlobalOptions {
+ String USE_MEMORY_TEMP_CACHE_OPTION = "use.memory.temp.cache";
+ String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process";
+ String GENERATE_CLASSPATH_INDEX_OPTION = "generate.classpath.index";
+ String COMPILE_PARALLEL_OPTION = "compile.parallel";
+ String COMPILE_PARALLEL_MAX_THREADS_OPTION = "compile.parallel.max.threads";
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/RequestFuture.java b/jps/jps-builders/src/org/jetbrains/jps/api/RequestFuture.java
new file mode 100644
index 000000000000..e06d8a1017e7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/RequestFuture.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.api;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 9/13/11
+*/
+public class RequestFuture<T> extends BasicFuture<T> {
+ private final T myHandler;
+ private final UUID myRequestID;
+ @Nullable private final CancelAction<T> myCancelAction;
+
+ public interface CancelAction<T> {
+ void cancel(RequestFuture<T> future) throws Exception;
+ }
+
+ public RequestFuture(T handler, UUID requestID, @Nullable CancelAction<T> cancelAction) {
+ super();
+ myCancelAction = cancelAction;
+ myHandler = handler;
+ myRequestID = requestID;
+ mySemaphore.acquireUninterruptibly();
+ }
+
+ public UUID getRequestID() {
+ return myRequestID;
+ }
+
+ public T getMessageHandler() {
+ return myHandler;
+ }
+
+ @Override
+ protected void performCancel() throws Exception {
+ if (myCancelAction != null) {
+ myCancelAction.cancel(this);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java b/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java
new file mode 100644
index 000000000000..6580d7b474ac
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class AdditionalRootsProviderService<R extends BuildRootDescriptor> {
+ private Collection<? extends BuildTargetType<? extends BuildTarget<R>>> myTargetTypes;
+
+ protected AdditionalRootsProviderService(Collection<? extends BuildTargetType<? extends BuildTarget<R>>> targetTypes) {
+ myTargetTypes = targetTypes;
+ }
+
+ public Collection<? extends BuildTargetType<? extends BuildTarget<R>>> getTargetTypes() {
+ return myTargetTypes;
+ }
+
+ @NotNull
+ public List<R> getAdditionalRoots(@NotNull BuildTarget<R> target, BuildDataPaths dataPaths) {
+ return Collections.emptyList();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java
new file mode 100644
index 000000000000..49f0cf7649ba
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface BuildOutputConsumer {
+ void registerOutputFile(File outputFile, Collection<String> sourcePaths) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
new file mode 100644
index 000000000000..001c955249c0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public abstract class BuildRootDescriptor {
+ public abstract String getRootId();
+
+ public abstract File getRootFile();
+
+ public abstract BuildTarget<?> getTarget();
+
+ public abstract FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor);
+
+ /**
+ * @return the set of excluded directories under this root
+ */
+ @NotNull
+ public Set<File> getExcludedRoots() {
+ return Collections.emptySet();
+ }
+
+ public boolean isGenerated() {
+ return false;
+ }
+
+ public boolean canUseFileCache() {
+ return false;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java
new file mode 100644
index 000000000000..b8065df7acc6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface BuildRootIndex {
+
+ @NotNull
+ <R extends BuildRootDescriptor> List<R> getTargetRoots(@NotNull BuildTarget<R> target, @Nullable CompileContext context);
+
+ @NotNull
+ <R extends BuildRootDescriptor> List<R> getTempTargetRoots(@NotNull BuildTarget<R> target, @NotNull CompileContext context);
+
+ @NotNull
+ <R extends BuildRootDescriptor> List<R> getRootDescriptors(@NotNull File root, @Nullable Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context);
+
+ <R extends BuildRootDescriptor> void associateTempRoot(@NotNull CompileContext context, @NotNull BuildTarget<R> target, @NotNull R root);
+
+ @NotNull
+ Collection<? extends BuildRootDescriptor> clearTempRoots(@NotNull CompileContext context);
+
+ @Nullable
+ <R extends BuildRootDescriptor> R findParentDescriptor(@NotNull File file, @NotNull Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context);
+
+ @NotNull
+ <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file,
+ @Nullable Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context);
+
+ @NotNull
+ <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file, @Nullable CompileContext context);
+
+ @Nullable
+ JavaSourceRootDescriptor findJavaRootDescriptor(@Nullable CompileContext context, File file);
+
+ @NotNull
+ FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor, @NotNull ProjectDescriptor projectDescriptor);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java
new file mode 100644
index 000000000000..c8e992f89181
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class BuildTarget<R extends BuildRootDescriptor> {
+ private final BuildTargetType<?> myTargetType;
+
+ protected BuildTarget(BuildTargetType<?> targetType) {
+ myTargetType = targetType;
+ }
+
+ public abstract String getId();
+
+ public final BuildTargetType<?> getTargetType() {
+ return myTargetType;
+ }
+
+ public abstract Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex);
+
+ public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+ }
+
+ @NotNull
+ public abstract List<R> computeRootDescriptors(JpsModel model,
+ ModuleExcludeIndex index,
+ IgnoredFileIndex ignoredFileIndex,
+ BuildDataPaths dataPaths);
+
+ @Nullable
+ public abstract R findRootDescriptor(String rootId, BuildRootIndex rootIndex);
+
+ @NotNull
+ public abstract String getPresentableName();
+
+ @NotNull
+ public abstract Collection<File> getOutputRoots(CompileContext context);
+
+ @Override
+ public String toString() {
+ return getPresentableName();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetIndex.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetIndex.java
new file mode 100644
index 000000000000..63fa6e56f176
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetIndex.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public interface BuildTargetIndex extends BuildTargetRegistry {
+
+ List<BuildTargetChunk> getSortedTargetChunks(@NotNull CompileContext context);
+
+ @Deprecated
+ Set<BuildTarget<?>> getDependenciesRecursively(@NotNull BuildTarget<?> target, @NotNull CompileContext context);
+
+ @NotNull
+ Collection<BuildTarget<?>> getDependencies(@NotNull BuildTarget<?> target, @NotNull CompileContext context);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetLoader.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetLoader.java
new file mode 100644
index 000000000000..68a4a35ac12b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetLoader.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public abstract class BuildTargetLoader<T extends BuildTarget<?>> {
+ @Nullable
+ public abstract T createTarget(@NotNull String targetId);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetRegistry.java
new file mode 100644
index 000000000000..1dc5788220a2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetRegistry.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/27/12
+ */
+public interface BuildTargetRegistry {
+ @NotNull
+ <T extends BuildTarget<?>>
+ List<T> getAllTargets(@NotNull BuildTargetType<T> type);
+
+ List<? extends BuildTarget<?>> getAllTargets();
+
+ enum ModuleTargetSelector {
+ PRODUCTION, TEST, ALL
+ }
+ Collection<ModuleBasedTarget<?>> getModuleBasedTargets(@NotNull JpsModule module, @NotNull ModuleTargetSelector selector);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java
new file mode 100644
index 000000000000..496ad4778925
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class BuildTargetType<T extends BuildTarget<?>> {
+ private final String myTypeId;
+
+ protected BuildTargetType(String typeId) {
+ myTypeId = typeId;
+ }
+
+ public final String getTypeId() {
+ return myTypeId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof BuildTargetType && ((BuildTargetType)obj).myTypeId.equals(myTypeId);
+ }
+
+ @Override
+ public int hashCode() {
+ return myTypeId.hashCode();
+ }
+
+ @NotNull
+ public abstract List<T> computeAllTargets(@NotNull JpsModel model);
+
+ @NotNull
+ public abstract BuildTargetLoader<T> createLoader(@NotNull JpsModel model);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java b/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java
new file mode 100644
index 000000000000..3a1eaac159a7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface DirtyFilesHolder<R extends BuildRootDescriptor, T extends BuildTarget<R>> {
+ void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException;
+
+ boolean hasDirtyFiles() throws IOException;
+
+ boolean hasRemovedFiles();
+
+ @NotNull
+ Collection<String> getRemovedFiles(@NotNull T target);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/FileProcessor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/FileProcessor.java
new file mode 100644
index 000000000000..acdc7c3e0a99
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/FileProcessor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 9/21/11
+*/
+public interface FileProcessor<R extends BuildRootDescriptor, T extends BuildTarget<R>> {
+ /**
+ * @return true if processing should continue, false if should stop
+ */
+ boolean apply(T target, File file, R root) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java
new file mode 100644
index 000000000000..a2d070990466
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/27/12
+ */
+public abstract class ModuleBasedTarget<R extends BuildRootDescriptor> extends BuildTarget<R> {
+ protected final JpsModule myModule;
+
+ public ModuleBasedTarget(BuildTargetType<?> targetType, @NotNull JpsModule module) {
+ super(targetType);
+ myModule = module;
+ }
+
+ @NotNull
+ public JpsModule getModule() {
+ return myModule;
+ }
+
+ public boolean isCompiledBeforeModuleLevelBuilders() {
+ return false;
+ }
+
+ public abstract boolean isTests();
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || !(o instanceof ModuleBasedTarget)) {
+ return false;
+ }
+
+ ModuleBasedTarget target = (ModuleBasedTarget)o;
+ return getTargetType() == target.getTargetType() && getId().equals(target.getId());
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * getId().hashCode() + getTargetType().hashCode();
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/TargetOutputIndex.java b/jps/jps-builders/src/org/jetbrains/jps/builders/TargetOutputIndex.java
new file mode 100644
index 000000000000..8f3b6497f421
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/TargetOutputIndex.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface TargetOutputIndex {
+ Collection<BuildTarget<?>> getTargetsByOutputFile(@NotNull File file);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/ArtifactBuildTaskProvider.java b/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/ArtifactBuildTaskProvider.java
new file mode 100644
index 000000000000..0569e1917886
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/ArtifactBuildTaskProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.artifacts;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.BuildTask;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class ArtifactBuildTaskProvider {
+ public enum ArtifactBuildPhase {
+ PRE_PROCESSING, POST_PROCESSING
+ }
+
+ @NotNull
+ public abstract List<? extends BuildTask> createArtifactBuildTasks(@NotNull JpsArtifact artifact, @NotNull ArtifactBuildPhase buildPhase);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/impl/ArtifactOutToSourceStorageProvider.java b/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/impl/ArtifactOutToSourceStorageProvider.java
new file mode 100644
index 000000000000..dba5ea54d590
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/artifacts/impl/ArtifactOutToSourceStorageProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.artifacts.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.StorageProvider;
+import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public class ArtifactOutToSourceStorageProvider extends StorageProvider<ArtifactOutputToSourceMapping> {
+ public static final ArtifactOutToSourceStorageProvider INSTANCE = new ArtifactOutToSourceStorageProvider();
+
+ private ArtifactOutToSourceStorageProvider() {
+ }
+
+ @NotNull
+ @Override
+ public ArtifactOutputToSourceMapping createStorage(File targetDataDir) throws IOException {
+ return new ArtifactOutputToSourceMapping(new File(targetDataDir, "out-src" + File.separator + "data"));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java
new file mode 100644
index 000000000000..6466ced6c62b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.util.PathUtilRt;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class BuildDataPathsImpl implements BuildDataPaths {
+ private final File myDataStorageRoot;
+
+ public BuildDataPathsImpl(File dataStorageRoot) {
+ myDataStorageRoot = dataStorageRoot;
+ }
+
+ @Override
+ public File getDataStorageRoot() {
+ return myDataStorageRoot;
+ }
+
+ @Override
+ public File getTargetsDataRoot() {
+ return new File(myDataStorageRoot, "targets");
+ }
+
+ @Override
+ public File getTargetTypeDataRoot(BuildTargetType<?> targetType) {
+ return new File(getTargetsDataRoot(), targetType.getTypeId());
+ }
+
+ @Override
+ public File getTargetDataRoot(BuildTarget<?> target) {
+ return new File(getTargetTypeDataRoot(target.getTargetType()), PathUtilRt.suggestFileName(target.getId(), true, false));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java
new file mode 100644
index 000000000000..5b0cf20e33be
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.FileGeneratedEvent;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 11/16/12
+*/
+public class BuildOutputConsumerImpl implements BuildOutputConsumer {
+ private final BuildTarget<?> myTarget;
+ private final CompileContext myContext;
+ private FileGeneratedEvent myFileGeneratedEvent;
+ private Collection<File> myOutputs;
+ private THashSet<String> myRegisteredSources = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+
+ public BuildOutputConsumerImpl(BuildTarget<?> target, CompileContext context) {
+ myTarget = target;
+ myContext = context;
+ myFileGeneratedEvent = new FileGeneratedEvent();
+ myOutputs = myTarget.getOutputRoots(context);
+ }
+
+ @Override
+ public void registerOutputFile(final File outputFile, Collection<String> sourcePaths) throws IOException {
+ final String outputFilePath = FileUtil.toSystemIndependentName(outputFile.getPath());
+ for (File outputRoot : myOutputs) {
+ String outputRootPath = FileUtil.toSystemIndependentName(outputRoot.getPath());
+ final String relativePath = FileUtil.getRelativePath(outputRootPath, outputFilePath, '/');
+ if (relativePath != null && !relativePath.startsWith("../")) {
+ // the relative path must be under the root or equal to it
+ myFileGeneratedEvent.add(outputRootPath, relativePath);
+ }
+ }
+ final SourceToOutputMapping mapping = myContext.getProjectDescriptor().dataManager.getSourceToOutputMap(myTarget);
+ for (String sourcePath : sourcePaths) {
+ if (myRegisteredSources.add(FileUtil.toSystemIndependentName(sourcePath))) {
+ mapping.setOutput(sourcePath, outputFilePath);
+ }
+ else {
+ mapping.appendOutput(sourcePath, outputFilePath);
+ }
+ }
+ }
+
+ public void fireFileGeneratedEvent() {
+ if (!myFileGeneratedEvent.getPaths().isEmpty()) {
+ myContext.processMessage(myFileGeneratedEvent);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java
new file mode 100644
index 000000000000..2143410c82ef
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+
+import java.io.File;
+import java.io.FileFilter;
+
+public class BuildRootDescriptorImpl extends BuildRootDescriptor {
+ private final File myRoot;
+ private final BuildTarget myTarget;
+ private final boolean myCanUseFileCache;
+
+ public BuildRootDescriptorImpl(BuildTarget target, File root) {
+ myTarget = target;
+ myRoot = root;
+ myCanUseFileCache = super.canUseFileCache();
+ }
+
+ public BuildRootDescriptorImpl(BuildTarget target, File root, boolean canUseFileCache) {
+ myTarget = target;
+ myRoot = root;
+ myCanUseFileCache = canUseFileCache;
+ }
+
+ @Override
+ public String getRootId() {
+ return FileUtilRt.toSystemIndependentName(myRoot.getAbsolutePath());
+ }
+
+ @Override
+ public File getRootFile() {
+ return myRoot;
+ }
+
+ @Override
+ public BuildTarget<?> getTarget() {
+ return myTarget;
+ }
+
+ @Override
+ public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ return new FileFilter() {
+ @Override
+ public boolean accept(@NotNull File pathname) {
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public boolean canUseFileCache() {
+ return myCanUseFileCache;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
new file mode 100644
index 000000000000..bb89a37158a7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ConcurrentHashMap;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.*;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author nik
+ */
+public class BuildRootIndexImpl implements BuildRootIndex {
+ private static final Key<Map<File, BuildRootDescriptor>> ROOT_DESCRIPTOR_MAP = Key.create("_root_to_descriptor_map");
+ private static final Key<Map<BuildTarget<?>, List<? extends BuildRootDescriptor>>> TEMP_TARGET_ROOTS_MAP = Key.create("_module_to_root_map");
+ private HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>> myRootsByTarget;
+ private THashMap<File,List<BuildRootDescriptor>> myRootToDescriptors;
+ private ConcurrentMap<BuildRootDescriptor, FileFilter> myFileFilters;
+
+ public BuildRootIndexImpl(BuildTargetIndex targetIndex, JpsModel model, ModuleExcludeIndex index,
+ BuildDataPaths dataPaths, final IgnoredFileIndex ignoredFileIndex) {
+ myRootsByTarget = new HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>>();
+ myRootToDescriptors = new THashMap<File, List<BuildRootDescriptor>>(FileUtil.FILE_HASHING_STRATEGY);
+ myFileFilters = new ConcurrentHashMap<BuildRootDescriptor, FileFilter>();
+ final Iterable<AdditionalRootsProviderService> rootsProviders = JpsServiceManager.getInstance().getExtensions(AdditionalRootsProviderService.class);
+ for (BuildTargetType<?> targetType : BuilderRegistry.getInstance().getTargetTypes()) {
+ for (BuildTarget<?> target : targetIndex.getAllTargets(targetType)) {
+ addRoots(dataPaths, rootsProviders, target, model, index, ignoredFileIndex);
+ }
+ }
+ }
+
+ private <R extends BuildRootDescriptor> void addRoots(BuildDataPaths dataPaths, Iterable<AdditionalRootsProviderService> rootsProviders,
+ BuildTarget<R> target,
+ JpsModel model,
+ ModuleExcludeIndex index,
+ IgnoredFileIndex ignoredFileIndex) {
+ List<R> descriptors = target.computeRootDescriptors(model, index, ignoredFileIndex, dataPaths);
+ for (AdditionalRootsProviderService<?> provider : rootsProviders) {
+ if (provider.getTargetTypes().contains(target.getTargetType())) {
+ //noinspection unchecked
+ AdditionalRootsProviderService<R> providerService = (AdditionalRootsProviderService<R>)provider;
+ final List<R> additionalRoots = providerService.getAdditionalRoots(target, dataPaths);
+ if (!additionalRoots.isEmpty()) {
+ descriptors = new ArrayList<R>(descriptors);
+ descriptors.addAll(additionalRoots);
+ }
+ }
+ }
+ for (BuildRootDescriptor descriptor : descriptors) {
+ registerDescriptor(descriptor);
+ }
+ myRootsByTarget.put(target, descriptors);
+ }
+
+ private void registerDescriptor(BuildRootDescriptor descriptor) {
+ List<BuildRootDescriptor> list = myRootToDescriptors.get(descriptor.getRootFile());
+ if (list == null) {
+ list = new SmartList<BuildRootDescriptor>();
+ myRootToDescriptors.put(descriptor.getRootFile(), list);
+ }
+ list.add(descriptor);
+ }
+
+ private static Map<String, List<ModuleBuildTarget>> buildModuleNameToTargetsMap(BuildTargetIndex targetIndex) {
+ final Map<String, List<ModuleBuildTarget>> moduleNameToTargetsMap = new HashMap<String, List<ModuleBuildTarget>>();
+ for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
+ for (ModuleBuildTarget target : targetIndex.getAllTargets(type)) {
+ final String moduleName = target.getModule().getName();
+ List<ModuleBuildTarget> targets = moduleNameToTargetsMap.get(moduleName);
+ if (targets == null) {
+ targets = new ArrayList<ModuleBuildTarget>();
+ moduleNameToTargetsMap.put(moduleName, targets);
+ }
+ targets.add(target);
+ }
+ }
+ return moduleNameToTargetsMap;
+ }
+
+ @NotNull
+ @Override
+ public <R extends BuildRootDescriptor> List<R> getRootDescriptors(@NotNull File root,
+ @Nullable Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context) {
+ List<BuildRootDescriptor> descriptors = myRootToDescriptors.get(root);
+ List<R> result = new SmartList<R>();
+ if (descriptors != null) {
+ for (BuildRootDescriptor descriptor : descriptors) {
+ if (types == null || types.contains(descriptor.getTarget().getTargetType())) {
+ //noinspection unchecked
+ result.add((R)descriptor);
+ }
+ }
+ }
+ if (context != null) {
+ final Map<File, BuildRootDescriptor> contextMap = ROOT_DESCRIPTOR_MAP.get(context);
+ if (contextMap != null) {
+ BuildRootDescriptor descriptor = contextMap.get(root);
+ if (descriptor != null && (types == null || types.contains(descriptor.getTarget().getTargetType()))) {
+ //noinspection unchecked
+ result.add((R)descriptor);
+ }
+ }
+ }
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public <R extends BuildRootDescriptor> List<R> getTargetRoots(@NotNull BuildTarget<R> target, CompileContext context) {
+ //noinspection unchecked
+ List<R> roots = (List<R>)myRootsByTarget.get(target);
+ if (context != null) {
+ final List<R> tempDescriptors = getTempTargetRoots(target, context);
+ if (!tempDescriptors.isEmpty()) {
+ if (roots != null) {
+ roots = new ArrayList<R>(roots);
+ roots.addAll(tempDescriptors);
+ }
+ else {
+ roots = tempDescriptors;
+ }
+ }
+ }
+ return roots != null? Collections.unmodifiableList(roots) : Collections.<R>emptyList();
+ }
+
+ @NotNull
+ @Override
+ public <R extends BuildRootDescriptor> List<R> getTempTargetRoots(@NotNull BuildTarget<R> target, @NotNull CompileContext context) {
+ final Map<BuildTarget<?>, List<? extends BuildRootDescriptor>> contextMap = TEMP_TARGET_ROOTS_MAP.get(context);
+ //noinspection unchecked
+ final List<R> rootList = contextMap != null? (List<R>)contextMap.get(target) : null;
+ return rootList != null ? rootList : Collections.<R>emptyList();
+ }
+
+ @Override
+ public <R extends BuildRootDescriptor> void associateTempRoot(@NotNull CompileContext context, @NotNull BuildTarget<R> target, @NotNull R root) {
+ Map<File, BuildRootDescriptor> rootToDescriptorMap = ROOT_DESCRIPTOR_MAP.get(context);
+ if (rootToDescriptorMap == null) {
+ rootToDescriptorMap = new THashMap<File, BuildRootDescriptor>(FileUtil.FILE_HASHING_STRATEGY);
+ ROOT_DESCRIPTOR_MAP.set(context, rootToDescriptorMap);
+ }
+
+ Map<BuildTarget<?>, List<? extends BuildRootDescriptor>> targetToRootMap = TEMP_TARGET_ROOTS_MAP.get(context);
+ if (targetToRootMap == null) {
+ targetToRootMap = new HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>>();
+ TEMP_TARGET_ROOTS_MAP.set(context, targetToRootMap);
+ }
+
+ final BuildRootDescriptor d = rootToDescriptorMap.get(root.getRootFile());
+ if (d != null) {
+ return;
+ }
+
+ //noinspection unchecked
+ List<R> targetRoots = (List<R>)targetToRootMap.get(target);
+ if (targetRoots == null) {
+ targetRoots = new ArrayList<R>();
+ targetToRootMap.put(target, targetRoots);
+ }
+ rootToDescriptorMap.put(root.getRootFile(), root);
+ targetRoots.add(root);
+ }
+
+ @Override
+ @Nullable
+ public <R extends BuildRootDescriptor> R findParentDescriptor(@NotNull File file, @NotNull Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context) {
+ File current = file;
+ while (current != null) {
+ final List<R> descriptors = getRootDescriptors(current, types, context);
+ if (!descriptors.isEmpty()) {
+ return descriptors.get(0);
+ }
+ current = FileUtilRt.getParentFile(current);
+ }
+ return null;
+ }
+
+
+
+ @Override
+ @NotNull
+ public <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file,
+ @Nullable Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
+ @Nullable CompileContext context) {
+ File current = file;
+ Collection<R> result = null;
+ while (current != null) {
+ List<R> descriptors = getRootDescriptors(current, types, context);
+ if (!descriptors.isEmpty()) {
+ if (result == null) {
+ result = descriptors;
+ }
+ else {
+ result = new ArrayList<R>(result);
+ result.addAll(descriptors);
+ }
+ }
+ current = FileUtilRt.getParentFile(current);
+ }
+ return result != null ? result : Collections.<R>emptyList();
+ }
+
+ @NotNull
+ @Override
+ public <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file, @Nullable CompileContext context) {
+ return findAllParentDescriptors(file, null, context);
+ }
+
+ @Override
+ @NotNull
+ public Collection<? extends BuildRootDescriptor> clearTempRoots(@NotNull CompileContext context) {
+ try {
+ final Map<File, BuildRootDescriptor> map = ROOT_DESCRIPTOR_MAP.get(context);
+ return map != null? map.values() : Collections.<BuildRootDescriptor>emptyList();
+ }
+ finally {
+ TEMP_TARGET_ROOTS_MAP.set(context, null);
+ ROOT_DESCRIPTOR_MAP.set(context, null);
+ }
+ }
+
+ @Override
+ @Nullable
+ public JavaSourceRootDescriptor findJavaRootDescriptor(@Nullable CompileContext context, File file) {
+ return findParentDescriptor(file, JavaModuleBuildTargetType.ALL_TYPES, context);
+ }
+
+ @NotNull
+ @Override
+ public FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor, @NotNull ProjectDescriptor projectDescriptor) {
+ FileFilter filter = myFileFilters.get(descriptor);
+ if (filter == null) {
+ filter = descriptor.createFileFilter(projectDescriptor);
+ myFileFilters.put(descriptor, filter);
+ }
+ return filter;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetChunk.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetChunk.java
new file mode 100644
index 000000000000..b567483530e0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetChunk.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import org.jetbrains.jps.builders.BuildTarget;
+
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class BuildTargetChunk {
+ private Set<BuildTarget<?>> myTargets;
+
+ public BuildTargetChunk(Set<BuildTarget<?>> targets) {
+ myTargets = targets;
+ }
+
+ public Set<BuildTarget<?>> getTargets() {
+ return myTargets;
+ }
+
+ @Override
+ public String toString() {
+ return myTargets.toString();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java
new file mode 100644
index 000000000000..245e39df571a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.graph.CachingSemiGraph;
+import com.intellij.util.graph.DFSTBuilder;
+import com.intellij.util.graph.GraphGenerator;
+import gnu.trove.THashMap;
+import gnu.trove.TIntArrayList;
+import gnu.trove.TIntProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class BuildTargetIndexImpl implements BuildTargetIndex {
+ private Map<BuildTargetType<?>, List<? extends BuildTarget<?>>> myTargets;
+ private Map<JpsModule, List<ModuleBasedTarget>> myModuleBasedTargets;
+ private Map<BuildTarget<?>, Collection<BuildTarget<?>>> myDependencies;
+ private List<BuildTargetChunk> myTargetChunks;
+ private final List<BuildTarget<?>> myAllTargets;
+
+ public BuildTargetIndexImpl(@NotNull JpsModel model) {
+ myTargets = new THashMap<BuildTargetType<?>, List<? extends BuildTarget<?>>>();
+ myModuleBasedTargets = new THashMap<JpsModule, List<ModuleBasedTarget>>();
+ List<List<? extends BuildTarget<?>>> targetsByType = new ArrayList<List<? extends BuildTarget<?>>>();
+ for (BuildTargetType<?> type : BuilderRegistry.getInstance().getTargetTypes()) {
+ List<? extends BuildTarget<?>> targets = type.computeAllTargets(model);
+ myTargets.put(type, targets);
+ targetsByType.add(targets);
+ for (BuildTarget<?> target : targets) {
+ if (target instanceof ModuleBasedTarget) {
+ final ModuleBasedTarget t = (ModuleBasedTarget)target;
+ final JpsModule module = t.getModule();
+ List<ModuleBasedTarget> list = myModuleBasedTargets.get(module);
+ if (list == null) {
+ list = new ArrayList<ModuleBasedTarget>();
+ myModuleBasedTargets.put(module, list);
+ }
+ list.add(t);
+ }
+ }
+ }
+ myDependencies = new THashMap<BuildTarget<?>, Collection<BuildTarget<?>>>();
+ myAllTargets = Collections.unmodifiableList(ContainerUtil.concat(targetsByType));
+ }
+
+ @Override
+ public Collection<ModuleBasedTarget<?>> getModuleBasedTargets(@NotNull JpsModule module, @NotNull ModuleTargetSelector selector) {
+ final List<ModuleBasedTarget> targets = myModuleBasedTargets.get(module);
+ if (targets == null || targets.isEmpty()) {
+ return Collections.emptyList();
+ }
+ final List<ModuleBasedTarget<?>> result = new SmartList<ModuleBasedTarget<?>>();
+ for (ModuleBasedTarget target : targets) {
+ switch (selector) {
+ case ALL:
+ result.add(target);
+ break;
+ case PRODUCTION:
+ if (!target.isTests()) {
+ result.add(target);
+ }
+ break;
+ case TEST:
+ if (target.isTests()) {
+ result.add(target);
+ }
+ }
+ }
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public <T extends BuildTarget<?>> List<T> getAllTargets(@NotNull BuildTargetType<T> type) {
+ //noinspection unchecked
+ return (List<T>)myTargets.get(type);
+ }
+
+ @Override
+ public List<BuildTargetChunk> getSortedTargetChunks(@NotNull CompileContext context) {
+ initializeChunks(context);
+ return myTargetChunks;
+ }
+
+
+ private synchronized void initializeChunks(@NotNull CompileContext context) {
+ if (myTargetChunks != null) {
+ return;
+ }
+
+ final List<? extends BuildTarget<?>> allTargets = getAllTargets();
+ TargetOutputIndex outputIndex = new TargetOutputIndexImpl(allTargets, context);
+ for (BuildTarget<?> target : allTargets) {
+ myDependencies.put(target, target.computeDependencies(this, outputIndex));
+ }
+
+ GraphGenerator<BuildTarget<?>>
+ graph = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<BuildTarget<?>>() {
+ @Override
+ public Collection<BuildTarget<?>> getNodes() {
+ return myAllTargets;
+ }
+
+ @Override
+ public Iterator<BuildTarget<?>> getIn(BuildTarget<?> n) {
+ return myDependencies.get(n).iterator();
+ }
+ }));
+
+ final DFSTBuilder<BuildTarget<?>> builder = new DFSTBuilder<BuildTarget<?>>(graph);
+ final TIntArrayList sccs = builder.getSCCs();
+
+ myTargetChunks = new ArrayList<BuildTargetChunk>(sccs.size());
+ sccs.forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ final Set<BuildTarget<?>> chunkNodes = new LinkedHashSet<BuildTarget<?>>();
+ for (int j = 0; j < size; j++) {
+ final BuildTarget<?> node = builder.getNodeByTNumber(myTNumber + j);
+ chunkNodes.add(node);
+ }
+ myTargetChunks.add(new BuildTargetChunk(chunkNodes));
+
+ myTNumber += size;
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public List<? extends BuildTarget<?>> getAllTargets() {
+ return myAllTargets;
+ }
+
+ @Override
+ public Set<BuildTarget<?>> getDependenciesRecursively(@NotNull BuildTarget<?> target, @NotNull CompileContext context) {
+ initializeChunks(context);
+ LinkedHashSet<BuildTarget<?>> result = new LinkedHashSet<BuildTarget<?>>();
+ for (BuildTarget<?> dep : myDependencies.get(target)) {
+ collectDependenciesRecursively(dep, result);
+ }
+ return result;
+ }
+
+ private void collectDependenciesRecursively(BuildTarget<?> target, LinkedHashSet<BuildTarget<?>> result) {
+ if (result.add(target)) {
+ for (BuildTarget<?> dep : myDependencies.get(target)) {
+ collectDependenciesRecursively(dep, result);
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public Collection<BuildTarget<?>> getDependencies(@NotNull BuildTarget<?> target, @NotNull CompileContext context) {
+ initializeChunks(context);
+ return myDependencies.get(target);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java
new file mode 100644
index 000000000000..b10637a56fce
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.openapi.util.Ref;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public abstract class DirtyFilesHolderBase<R extends BuildRootDescriptor, T extends BuildTarget<R>> implements DirtyFilesHolder<R, T> {
+ protected final CompileContext myContext;
+
+ public DirtyFilesHolderBase(CompileContext context) {
+ myContext = context;
+ }
+
+ @Override
+ public boolean hasDirtyFiles() throws IOException {
+ final Ref<Boolean> hasDirtyFiles = Ref.create(false);
+ processDirtyFiles(new FileProcessor<R, T>() {
+ @Override
+ public boolean apply(T target, File file, R root) throws IOException {
+ hasDirtyFiles.set(true);
+ return false;
+ }
+ });
+ return hasDirtyFiles.get();
+ }
+
+ @Override
+ public boolean hasRemovedFiles() {
+ Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(myContext);
+ return map != null && !map.isEmpty();
+ }
+
+ @NotNull
+ @Override
+ public Collection<String> getRemovedFiles(@NotNull T target) {
+ Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(myContext);
+ if (map != null) {
+ Collection<String> paths = map.get(target);
+ if (paths != null) {
+ return paths;
+ }
+ }
+ return Collections.emptyList();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/TargetOutputIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/TargetOutputIndexImpl.java
new file mode 100644
index 000000000000..d47a4318b9ca
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/TargetOutputIndexImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.SmartList;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.TargetOutputIndex;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class TargetOutputIndexImpl implements TargetOutputIndex {
+ private final Map<File, List<BuildTarget<?>>> myOutputToTargets;
+
+ public TargetOutputIndexImpl(Collection<? extends BuildTarget<?>> allTargets, CompileContext context) {
+ myOutputToTargets = new THashMap<File, List<BuildTarget<?>>>(FileUtil.FILE_HASHING_STRATEGY);
+ for (BuildTarget<?> target : allTargets) {
+ Collection<File> roots = target.getOutputRoots(context);
+ for (File root : roots) {
+ List<BuildTarget<?>> targets = myOutputToTargets.get(root);
+ if (targets == null) {
+ targets = new SmartList<BuildTarget<?>>();
+ myOutputToTargets.put(root, targets);
+ }
+ targets.add(target);
+ }
+ }
+ }
+
+ @Override
+ public Collection<BuildTarget<?>> getTargetsByOutputFile(@NotNull File file) {
+ File current = file;
+ Collection<BuildTarget<?>> result = null;
+ while (current != null) {
+ List<BuildTarget<?>> targets = myOutputToTargets.get(current);
+ if (targets != null) {
+ if (result == null) {
+ result = targets;
+ }
+ else {
+ result = new ArrayList<BuildTarget<?>>(result);
+ result.addAll(targets);
+ }
+ }
+ current = FileUtilRt.getParentFile(current);
+ }
+ return result != null ? result : Collections.<BuildTarget<?>>emptyList();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java
new file mode 100644
index 000000000000..806069a93e7e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl.logging;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class ProjectBuilderLoggerBase implements ProjectBuilderLogger {
+ @Override
+ public void logDeletedFiles(Collection<String> paths) {
+ if (paths.isEmpty()) return;
+ final String[] buffer = new String[paths.size()];
+ int i = 0;
+ for (final String o : paths) {
+ buffer[i++] = o;
+ }
+ Arrays.sort(buffer);
+ logLine("Cleaning output files:");
+ for (final String o : buffer) {
+ logLine(o);
+ }
+ logLine("End of files");
+ }
+
+ @Override
+ public void logCompiledFiles(Collection<File> files, String builderName, final String description) throws IOException {
+ logLine(description);
+ final String[] buffer = new String[files.size()];
+ int i = 0;
+ for (final File f : files) {
+ buffer[i++] = FileUtil.toSystemIndependentName(f.getCanonicalPath());
+ }
+ Arrays.sort(buffer);
+ for (final String s : buffer) {
+ logLine(s);
+ }
+ logLine("End of files");
+ }
+
+ @Override
+ public void logCompiledPaths(Collection<String> paths, String builderName, String description) throws IOException {
+ List<File> files = new ArrayList<File>(paths.size());
+ for (String path : paths) {
+ files.add(new File(path));
+ }
+ logCompiledFiles(files, builderName, description);
+ }
+
+ protected abstract void logLine(String message);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java
new file mode 100644
index 000000000000..ef99f3e6d71e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl.logging;
+
+import com.intellij.openapi.diagnostic.Logger;
+
+/**
+ * @author nik
+ */
+public class ProjectBuilderLoggerImpl extends ProjectBuilderLoggerBase {
+ private static final Logger LOG = Logger.getInstance(ProjectBuilderLoggerImpl.class);
+
+ @Override
+ public boolean isEnabled() {
+ return LOG.isDebugEnabled();
+ }
+
+ @Override
+ protected void logLine(final String message) {
+ LOG.debug(message);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java
new file mode 100644
index 000000000000..4e64ce68afa3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.impl.storage;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.builders.storage.StorageProvider;
+import org.jetbrains.jps.incremental.storage.CompositeStorageOwner;
+import org.jetbrains.jps.incremental.storage.StorageOwner;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class BuildTargetStorages extends CompositeStorageOwner {
+ private final BuildTarget<?> myTarget;
+ private final BuildDataPaths myPaths;
+ private Map<StorageProvider<?>, StorageOwner> myStorages = new HashMap<StorageProvider<?>, StorageOwner>();
+
+ public BuildTargetStorages(BuildTarget<?> target, BuildDataPaths paths) {
+ myTarget = target;
+ myPaths = paths;
+ }
+
+ @NotNull
+ public <S extends StorageOwner> S getOrCreateStorage(@NotNull StorageProvider<S> provider) throws IOException {
+ //noinspection unchecked
+ S storage = (S)myStorages.get(provider);
+ if (storage == null) {
+ storage = provider.createStorage(myPaths.getTargetDataRoot(myTarget));
+ myStorages.put(provider, storage);
+ }
+ return (S)storage;
+ }
+
+ @Override
+ protected Iterable<? extends StorageOwner> getChildStorages() {
+ return myStorages.values();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ExcludedJavaSourceRootProvider.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ExcludedJavaSourceRootProvider.java
new file mode 100644
index 000000000000..18b1a52a9ffb
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ExcludedJavaSourceRootProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+
+/**
+ *
+ * @author nik
+ */
+public abstract class ExcludedJavaSourceRootProvider {
+ public abstract boolean isExcludedFromCompilation(@NotNull JpsModule module, @NotNull JpsModuleSourceRoot root);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
new file mode 100644
index 000000000000..58b6a4ca4aba
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.builders.java.dependencyView.Mappings;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JavaBuilderUtil {
+ private static final Key<Set<File>> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
+ private static final Key<Set<File>> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
+ public static final Key<Callbacks.ConstantAffectionResolver> CONSTANT_SEARCH_SERVICE = Key.create("_constant_search_service_");
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder");
+
+ /**
+ *
+ * @param context
+ * @param delta
+ * @param dirtyFilesHolder
+ * @param chunk
+ * @param filesToCompile files compiled in this round
+ * @param successfullyCompiled
+ * @return true if additional compilation pass is required, false otherwise
+ * @throws Exception
+ */
+ public static boolean updateMappings(CompileContext context,
+ final Mappings delta,
+ DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
+ ModuleChunk chunk,
+ Collection<File> filesToCompile,
+ Collection<File> successfullyCompiled) throws IOException {
+ if (Utils.errorsDetected(context)) {
+ return false;
+ }
+ try {
+ boolean additionalPassRequired = false;
+
+ final Set<String> removedPaths = getRemovedPaths(chunk, dirtyFilesHolder);
+
+ final Mappings globalMappings = context.getProjectDescriptor().dataManager.getMappings();
+
+ if (!context.isProjectRebuild()) {
+ if (context.shouldDifferentiate(chunk)) {
+ context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getName() + "]"));
+ final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
+ final Set<File> allAffectedFiles = getAllAffectedFilesContainer(context);
+
+ // mark as affected all files that were dirty before compilation
+ allAffectedFiles.addAll(filesToCompile);
+ // accumulate all successfully compiled in this round
+ allCompiledFiles.addAll(successfullyCompiled);
+ // unmark as affected all successfully compiled
+ allAffectedFiles.removeAll(successfullyCompiled);
+
+ final Set<File> affectedBeforeDif = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ affectedBeforeDif.addAll(allAffectedFiles);
+
+ final ModulesBasedFileFilter moduleBasedFilter = new ModulesBasedFileFilter(context, chunk);
+ final boolean incremental = globalMappings.differentiateOnIncrementalMake(
+ delta, removedPaths, filesToCompile, allCompiledFiles, allAffectedFiles, moduleBasedFilter,
+ CONSTANT_SEARCH_SERVICE.get(context)
+ );
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Differentiate Results:");
+ LOG.debug(" Compiled Files:");
+ for (final File c : allCompiledFiles) {
+ LOG.debug(" " + c.getAbsolutePath());
+ }
+ LOG.debug(" Affected Files:");
+ for (final File c : allAffectedFiles) {
+ LOG.debug(" " + c.getAbsolutePath());
+ }
+ LOG.debug("End Of Differentiate Results.");
+ }
+
+ if (incremental) {
+ final Set<File> newlyAffectedFiles = new HashSet<File>(allAffectedFiles);
+ newlyAffectedFiles.removeAll(affectedBeforeDif);
+ newlyAffectedFiles.removeAll(allCompiledFiles); // the diff operation may have affected the class already compiled in thic compilation round
+
+ final String infoMessage = "Dependency analysis found " + newlyAffectedFiles.size() + " affected files";
+ LOG.info(infoMessage);
+ context.processMessage(new ProgressMessage(infoMessage));
+
+ if (!newlyAffectedFiles.isEmpty()) {
+
+ if (LOG.isDebugEnabled()) {
+ for (File file : newlyAffectedFiles) {
+ LOG.debug("affected file: " + file.getPath());
+ }
+ final List<Pair<File, JpsModule>> wrongFiles =
+ checkAffectedFilesInCorrectModules(context, newlyAffectedFiles, moduleBasedFilter);
+ if (!wrongFiles.isEmpty()) {
+ LOG.debug("Wrong affected files for module chunk " + chunk.getName() + ": ");
+ for (Pair<File, JpsModule> pair : wrongFiles) {
+ final String name = pair.second != null ? pair.second.getName() : "null";
+ LOG.debug("\t[" + name + "] " + pair.first.getPath());
+ }
+ }
+ }
+
+ for (File file : newlyAffectedFiles) {
+ FSOperations.markDirtyIfNotDeleted(context, file);
+ }
+ additionalPassRequired = context.isMake() && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
+ }
+ }
+ else {
+ final String messageText = "Marking " + chunk.getName() + " and direct dependants for recompilation";
+ LOG.info("Non-incremental mode: " + messageText);
+ context.processMessage(new ProgressMessage(messageText));
+
+ additionalPassRequired = context.isMake();
+ FSOperations.markDirtyRecursively(context, chunk);
+ }
+ }
+ else {
+ globalMappings.differentiateOnNonIncrementalMake(delta, removedPaths, filesToCompile);
+ }
+ }
+ else {
+ globalMappings.differentiateOnRebuild(delta);
+ }
+
+ context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getName() + "]"));
+
+ globalMappings.integrate(delta);
+
+ return additionalPassRequired;
+ }
+ catch (RuntimeException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw ((IOException)cause);
+ }
+ throw e;
+ }
+ finally {
+ context.processMessage(new ProgressMessage("")); // clean progress messages
+ }
+ }
+
+ private static List<Pair<File, JpsModule>> checkAffectedFilesInCorrectModules(CompileContext context,
+ Collection<File> affected,
+ ModulesBasedFileFilter moduleBasedFilter) {
+ if (affected.isEmpty()) {
+ return Collections.emptyList();
+ }
+ final List<Pair<File, JpsModule>> result = new ArrayList<Pair<File, JpsModule>>();
+ for (File file : affected) {
+ if (!moduleBasedFilter.accept(file)) {
+ final JavaSourceRootDescriptor moduleAndRoot = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context,
+ file);
+ result.add(Pair.create(file, moduleAndRoot != null ? moduleAndRoot.target.getModule() : null));
+ }
+ }
+ return result;
+ }
+
+ private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected)
+ throws IOException {
+ final Set<JpsModule> chunkModules = chunk.getModules();
+ if (!chunkModules.isEmpty()) {
+ for (File file : affected) {
+ final JavaSourceRootDescriptor moduleAndRoot = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context,
+ file);
+ if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.target.getModule())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static Set<File> getAllAffectedFilesContainer(CompileContext context) {
+ Set<File> allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context);
+ if (allAffectedFiles == null) {
+ allAffectedFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles);
+ }
+ return allAffectedFiles;
+ }
+
+ private static Set<File> getAllCompiledFilesContainer(CompileContext context) {
+ Set<File> allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
+ if (allCompiledFiles == null) {
+ allCompiledFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
+ }
+ return allCompiledFiles;
+ }
+
+ private static Set<String> getRemovedPaths(ModuleChunk chunk, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder) {
+ if (!dirtyFilesHolder.hasRemovedFiles()) {
+ return Collections.emptySet();
+ }
+ final Set<String> removed = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ removed.addAll(dirtyFilesHolder.getRemovedFiles(target));
+ }
+ return removed;
+ }
+
+ public static void cleanupChunkResources(CompileContext context) {
+ ALL_AFFECTED_FILES_KEY.set(context, null);
+ ALL_COMPILED_FILES_KEY.set(context, null);
+ }
+
+ @NotNull
+ public static JpsSdk<JpsDummyElement> ensureModuleHasJdk(JpsModule module, CompileContext context, final String compilerName) throws
+ ProjectBuildException {
+ JpsSdkReference<JpsDummyElement> reference = module.getSdkReference(JpsJavaSdkType.INSTANCE);
+ if (reference == null) {
+ context.processMessage(new CompilerMessage(compilerName, BuildMessage.Kind.ERROR, "JDK isn't specified for module '" + module.getName() + "'"));
+ throw new ProjectBuildException();
+ }
+
+ JpsTypedLibrary<JpsSdk<JpsDummyElement>> sdkLibrary = reference.resolve();
+ if (sdkLibrary == null) {
+ context.processMessage(new CompilerMessage(compilerName, BuildMessage.Kind.ERROR,
+ "Cannot find JDK '" + reference.getSdkName() + "' for module '" + module.getName() + "'"));
+ throw new ProjectBuildException();
+ }
+ return sdkLibrary.getProperties();
+ }
+
+ private static class ModulesBasedFileFilter implements Mappings.DependentFilesFilter {
+ private final CompileContext myContext;
+ private final Set<JpsModule> myChunkModules;
+ private final Map<JpsModule, Set<JpsModule>> myCache = new HashMap<JpsModule, Set<JpsModule>>();
+
+ private ModulesBasedFileFilter(CompileContext context, ModuleChunk chunk) {
+ myContext = context;
+ myChunkModules = chunk.getModules();
+ }
+
+ @Override
+ public boolean accept(File file) {
+ final JavaSourceRootDescriptor rd = myContext.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(myContext, file);
+ if (rd == null) {
+ return true;
+ }
+ final JpsModule moduleOfFile = rd.target.getModule();
+ if (myChunkModules.contains(moduleOfFile)) {
+ return true;
+ }
+ Set<JpsModule> moduleOfFileWithDependencies = myCache.get(moduleOfFile);
+ if (moduleOfFileWithDependencies == null) {
+ moduleOfFileWithDependencies = ProjectPaths.getModulesWithDependentsRecursively(moduleOfFile, true);
+ myCache.put(moduleOfFile, moduleOfFileWithDependencies);
+ }
+ return Utils.intersects(moduleOfFileWithDependencies, myChunkModules);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java
new file mode 100644
index 000000000000..3136780252f4
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JavaModuleBuildTargetType extends BuildTargetType<ModuleBuildTarget> {
+ public static final JavaModuleBuildTargetType PRODUCTION = new JavaModuleBuildTargetType("java-production", false);
+ public static final JavaModuleBuildTargetType TEST = new JavaModuleBuildTargetType("java-test", true);
+ public static final List<JavaModuleBuildTargetType> ALL_TYPES = Arrays.asList(PRODUCTION, TEST);
+
+ private boolean myTests;
+
+ private JavaModuleBuildTargetType(String typeId, boolean tests) {
+ super(typeId);
+ myTests = tests;
+ }
+
+ @NotNull
+ @Override
+ public List<ModuleBuildTarget> computeAllTargets(@NotNull JpsModel model) {
+ List<JpsModule> modules = model.getProject().getModules();
+ List<ModuleBuildTarget> targets = new ArrayList<ModuleBuildTarget>(modules.size());
+ for (JpsModule module : modules) {
+ targets.add(new ModuleBuildTarget(module, this));
+ }
+ return targets;
+ }
+
+ @NotNull
+ @Override
+ public Loader createLoader(@NotNull JpsModel model) {
+ return new Loader(model);
+ }
+
+ public boolean isTests() {
+ return myTests;
+ }
+
+ public static JavaModuleBuildTargetType getInstance(boolean tests) {
+ return tests ? TEST : PRODUCTION;
+ }
+
+ private class Loader extends BuildTargetLoader<ModuleBuildTarget> {
+ private final Map<String, JpsModule> myModules;
+
+ public Loader(JpsModel model) {
+ myModules = new HashMap<String, JpsModule>();
+ for (JpsModule module : model.getProject().getModules()) {
+ myModules.put(module.getName(), module);
+ }
+ }
+
+ @Nullable
+ @Override
+ public ModuleBuildTarget createTarget(@NotNull String targetId) {
+ JpsModule module = myModules.get(targetId);
+ return module != null ? new ModuleBuildTarget(module, JavaModuleBuildTargetType.this) : null;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
new file mode 100644
index 000000000000..3cae0f0aedfd
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Set;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/3/12
+*/
+public class JavaSourceRootDescriptor extends BuildRootDescriptor {
+ @NotNull
+ public final File root;
+ @NotNull
+ public final ModuleBuildTarget target;
+ public final boolean isGeneratedSources;
+ public final boolean isTemp;
+ private final String myPackagePrefix;
+ private final Set<File> myExcludes;
+
+ public JavaSourceRootDescriptor(@NotNull File root,
+ @NotNull ModuleBuildTarget target,
+ boolean isGenerated,
+ boolean isTemp,
+ @NotNull String packagePrefix,
+ @NotNull Set<File> excludes) {
+ this.root = root;
+ this.target = target;
+ this.isGeneratedSources = isGenerated;
+ this.isTemp = isTemp;
+ myPackagePrefix = packagePrefix;
+ myExcludes = excludes;
+ }
+
+ @Override
+ public String toString() {
+ return "RootDescriptor{" +
+ "target='" + target + '\'' +
+ ", root=" + root +
+ ", generated=" + isGeneratedSources +
+ '}';
+ }
+
+ @NotNull
+ @Override
+ public Set<File> getExcludedRoots() {
+ return myExcludes;
+ }
+
+ @NotNull
+ public String getPackagePrefix() {
+ return myPackagePrefix;
+ }
+
+ @Override
+ public String getRootId() {
+ return FileUtil.toSystemIndependentName(root.getPath());
+ }
+
+ @Override
+ public File getRootFile() {
+ return root;
+ }
+
+ @Override
+ public ModuleBuildTarget getTarget() {
+ return target;
+ }
+
+ @Override
+ public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(target.getModule().getProject()).getCompilerExcludes();
+ return new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return !excludes.isExcluded(file);
+ }
+ };
+ }
+
+ @Override
+ public boolean isGenerated() {
+ return isGeneratedSources;
+ }
+
+ @Override
+ public boolean canUseFileCache() {
+ return true;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
new file mode 100644
index 000000000000..949fbc2b4fb4
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.ResourcesTarget;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Set;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/3/12
+*/
+public final class ResourceRootDescriptor extends BuildRootDescriptor {
+
+ @NotNull private final File myRoot;
+ @NotNull private final ResourcesTarget myTarget;
+ private final boolean myGenerated;
+ @NotNull private final String myPackagePrefix;
+ @NotNull private final Set<File> myExcludes;
+
+ public ResourceRootDescriptor(@NotNull File root, @NotNull ResourcesTarget target, boolean isGenerated, @NotNull String packagePrefix, @NotNull Set<File> excludes) {
+ myRoot = root;
+ myTarget = target;
+ myGenerated = isGenerated;
+ myPackagePrefix = packagePrefix;
+ myExcludes = excludes;
+ }
+
+ @Override
+ public String getRootId() {
+ return FileUtil.toSystemIndependentName(myRoot.getPath());
+ }
+
+ @Override
+ public File getRootFile() {
+ return myRoot;
+ }
+
+ @NotNull
+ @Override
+ public Set<File> getExcludedRoots() {
+ return myExcludes;
+ }
+
+ @Override
+ public ResourcesTarget getTarget() {
+ return myTarget;
+ }
+
+ @NotNull
+ public String getPackagePrefix() {
+ return myPackagePrefix;
+ }
+
+ @Override
+ public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ final JpsProject project = myTarget.getModule().getProject();
+ final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project).getCompilerExcludes();
+ return new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return !excludes.isExcluded(file);
+ }
+ };
+ }
+
+ @Override
+ public boolean isGenerated() {
+ return myGenerated;
+ }
+
+ @Override
+ public String toString() {
+ return "ResourceRootDescriptor{" +
+ "target='" + myTarget + '\'' +
+ ", root=" + myRoot +
+ ", generated=" + myGenerated +
+ '}';
+ }
+
+ @Override
+ public boolean canUseFileCache() {
+ return true;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java
new file mode 100644
index 000000000000..0e2219ccf249
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.incremental.ResourcesTarget;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class ResourcesTargetType extends BuildTargetType<ResourcesTarget> {
+ public static final ResourcesTargetType PRODUCTION = new ResourcesTargetType("resources-production", false);
+ public static final ResourcesTargetType TEST = new ResourcesTargetType("resources-test", true);
+ public static final List<ResourcesTargetType> ALL_TYPES = Arrays.asList(PRODUCTION, TEST);
+
+ private boolean myTests;
+
+ private ResourcesTargetType(String typeId, boolean tests) {
+ super(typeId);
+ myTests = tests;
+ }
+
+ @NotNull
+ @Override
+ public List<ResourcesTarget> computeAllTargets(@NotNull JpsModel model) {
+ List<JpsModule> modules = model.getProject().getModules();
+ List<ResourcesTarget> targets = new ArrayList<ResourcesTarget>(modules.size());
+ for (JpsModule module : modules) {
+ targets.add(new ResourcesTarget(module, this));
+ }
+ return targets;
+ }
+
+ @NotNull
+ @Override
+ public Loader createLoader(@NotNull JpsModel model) {
+ return new Loader(model);
+ }
+
+ public boolean isTests() {
+ return myTests;
+ }
+
+ public static ResourcesTargetType getInstance(boolean tests) {
+ return tests ? TEST : PRODUCTION;
+ }
+
+ private class Loader extends BuildTargetLoader<ResourcesTarget> {
+ private final Map<String, JpsModule> myModules;
+
+ public Loader(JpsModel model) {
+ myModules = new HashMap<String, JpsModule>();
+ for (JpsModule module : model.getProject().getModules()) {
+ myModules.put(module.getName(), module);
+ }
+ }
+
+ @Nullable
+ @Override
+ public ResourcesTarget createTarget(@NotNull String targetId) {
+ JpsModule module = myModules.get(targetId);
+ return module != null ? new ResourcesTarget(module, ResourcesTargetType.this) : null;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
new file mode 100644
index 000000000000..ce3c2a4fc269
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import org.jetbrains.asm4.ClassReader;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.concurrent.Future;
+
+/**
+ * @author: db
+ * Date: 28.01.11
+ */
+public class Callbacks {
+
+ public interface Backend {
+ void associate(String classFileName, String sourceFileName, ClassReader cr);
+ void registerImports(String className, Collection<String> imports, Collection<String> staticImports);
+ }
+
+ public static class ConstantAffection {
+ public static final ConstantAffection EMPTY = new ConstantAffection();
+ private final boolean myKnown;
+ private final Collection<File> myAffectedFiles;
+
+ public ConstantAffection(final Collection<File> affectedFiles) {
+ myAffectedFiles = affectedFiles;
+ myKnown = true;
+ }
+
+ public ConstantAffection() {
+ myKnown = false;
+ myAffectedFiles = null;
+ }
+
+ public boolean isKnown(){
+ return myKnown;
+ }
+
+ public Collection<File> getAffectedFiles (){
+ return myAffectedFiles;
+ }
+ }
+
+ public interface ConstantAffectionResolver {
+ Future<ConstantAffection> request(final String ownerClassName,
+ final String fieldName,
+ int accessFlags,
+ boolean fieldRemoved,
+ boolean accessChanged);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
new file mode 100644
index 000000000000..d0df19162937
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.Opcodes;
+
+import java.io.*;
+import java.lang.annotation.RetentionPolicy;
+import java.util.*;
+
+/**
+ * @author: db
+ * Date: 01.02.11
+ */
+public class ClassRepr extends Proto {
+ private final DependencyContext myContext;
+ private final int myFileName;
+ private final TypeRepr.ClassType mySuperClass;
+ private final Set<TypeRepr.AbstractType> myInterfaces;
+ private final Set<ElemType> myAnnotationTargets;
+ private final RetentionPolicy myRetentionPolicy;
+
+ private final Set<FieldRepr> myFields;
+ private final Set<MethodRepr> myMethods;
+ private final Set<UsageRepr.Usage> myUsages;
+
+ private final int myOuterClassName;
+ private final boolean myIsLocal;
+ private final boolean myIsAnonymous;
+
+ public Set<MethodRepr> getMethods() {
+ return myMethods;
+ }
+
+ public Set<FieldRepr> getFields() {
+ return myFields;
+ }
+
+ public int getOuterClassName() {
+ return myOuterClassName;
+ }
+
+ public boolean isLocal() {
+ return myIsLocal;
+ }
+
+ public boolean isAnonymous() {
+ return myIsAnonymous;
+ }
+
+ public TypeRepr.ClassType getSuperClass() {
+ return mySuperClass;
+ }
+
+ public RetentionPolicy getRetentionPolicy() {
+ return myRetentionPolicy;
+ }
+
+ public Set<UsageRepr.Usage> getUsages() {
+ return myUsages;
+ }
+
+ public boolean addUsage(final UsageRepr.Usage usage) {
+ return myUsages.add(usage);
+ }
+
+ public abstract static class Diff extends Difference {
+ public abstract Specifier<TypeRepr.AbstractType> interfaces();
+
+ public abstract Specifier<FieldRepr> fields();
+
+ public abstract Specifier<MethodRepr> methods();
+
+ public abstract Specifier<ElemType> targets();
+
+ public abstract boolean retentionChanged();
+
+ public abstract boolean extendsAdded();
+
+ public boolean no() {
+ return base() == NONE &&
+ interfaces().unchanged() &&
+ fields().unchanged() &&
+ methods().unchanged() &&
+ targets().unchanged() &&
+ !retentionChanged();
+ }
+ }
+
+ public Diff difference(final Proto past) {
+ final ClassRepr pastClass = (ClassRepr)past;
+ final Difference diff = super.difference(past);
+ int base = diff.base();
+
+ if (!mySuperClass.equals(pastClass.mySuperClass)) {
+ base |= Difference.SUPERCLASS;
+ }
+
+ if (!myUsages.equals(pastClass.myUsages)) {
+ base |= Difference.USAGES;
+ }
+ final int d = base;
+
+ return new Diff() {
+ @Override
+ public boolean extendsAdded() {
+ if ((d & Difference.SUPERCLASS) <= 0) {
+ return false;
+ }
+ final String pastSuperName = myContext.getValue(((ClassRepr)past).mySuperClass.className);
+ return "java/lang/Object".equals(pastSuperName);
+ }
+
+ @Override
+ public boolean packageLocalOn() {
+ return diff.packageLocalOn();
+ }
+
+ @Override
+ public int addedModifiers() {
+ return diff.addedModifiers();
+ }
+
+ @Override
+ public int removedModifiers() {
+ return diff.removedModifiers();
+ }
+
+ @Override
+ public Difference.Specifier<TypeRepr.AbstractType> interfaces() {
+ return Difference.make(pastClass.myInterfaces, myInterfaces);
+ }
+
+ @Override
+ public Difference.Specifier<FieldRepr> fields() {
+ return Difference.make(pastClass.myFields, myFields);
+ }
+
+ @Override
+ public Difference.Specifier<MethodRepr> methods() {
+ return Difference.make(pastClass.myMethods, myMethods);
+ }
+
+ @Override
+ public Specifier<ElemType> targets() {
+ return Difference.make(pastClass.myAnnotationTargets, myAnnotationTargets);
+ }
+
+ @Override
+ public boolean retentionChanged() {
+ return !((myRetentionPolicy == null && pastClass.myRetentionPolicy == RetentionPolicy.CLASS) ||
+ (myRetentionPolicy == RetentionPolicy.CLASS && pastClass.myRetentionPolicy == null) ||
+ (myRetentionPolicy == pastClass.myRetentionPolicy));
+ }
+
+ @Override
+ public int base() {
+ return d;
+ }
+
+ @Override
+ public boolean hadValue() {
+ return false;
+ }
+
+ @Override
+ public boolean weakedAccess() {
+ return diff.weakedAccess();
+ }
+ };
+ }
+
+ @NotNull
+ public int[] getSupers() {
+ final int[] result = new int[myInterfaces.size() + 1];
+
+ result[0] = mySuperClass.className;
+
+ int i = 1;
+ for (TypeRepr.AbstractType t : myInterfaces) {
+ result[i++] = ((TypeRepr.ClassType)t).className;
+ }
+
+ return result;
+ }
+
+ public void updateClassUsages(final DependencyContext context, final Set<UsageRepr.Usage> s) {
+ mySuperClass.updateClassUsages(context, name, s);
+
+ for (TypeRepr.AbstractType t : myInterfaces) {
+ t.updateClassUsages(context, name, s);
+ }
+
+ for (MethodRepr m : myMethods) {
+ m.updateClassUsages(context, name, s);
+ }
+
+ for (FieldRepr f : myFields) {
+ f.updateClassUsages(context, name, s);
+ }
+ }
+
+ public ClassRepr(final DependencyContext context, final int a, final int fn, final int n, final int sig,
+ final int sup,
+ final String[] i,
+ final Set<FieldRepr> f,
+ final Set<MethodRepr> m,
+ final Set<ElemType> targets,
+ final RetentionPolicy policy,
+ final int outerClassName,
+ final boolean localClassFlag,
+ final boolean anonymousClassFlag,
+ final Set<UsageRepr.Usage> usages) {
+ super(a, sig, n);
+ this.myContext = context;
+ myFileName = fn;
+ mySuperClass = TypeRepr.createClassType(context, sup);
+ myInterfaces = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, i, new HashSet<TypeRepr.AbstractType>());
+ myFields = f;
+ myMethods = m;
+ this.myAnnotationTargets = targets;
+ this.myRetentionPolicy = policy;
+ this.myOuterClassName = outerClassName;
+ this.myIsLocal = localClassFlag;
+ this.myIsAnonymous = anonymousClassFlag;
+ this.myUsages = usages;
+ }
+
+ public ClassRepr(final DependencyContext context, final DataInput in) {
+ super(in);
+ try {
+ this.myContext = context;
+ myFileName = in.readInt();
+ mySuperClass = (TypeRepr.ClassType)TypeRepr.externalizer(context).read(in);
+ myInterfaces = (Set<TypeRepr.AbstractType>)RW.read(TypeRepr.externalizer(context), new HashSet<TypeRepr.AbstractType>(), in);
+ myFields = (Set<FieldRepr>)RW.read(FieldRepr.externalizer(context), new HashSet<FieldRepr>(), in);
+ myMethods = (Set<MethodRepr>)RW.read(MethodRepr.externalizer(context), new HashSet<MethodRepr>(), in);
+ myAnnotationTargets = (Set<ElemType>)RW.read(UsageRepr.AnnotationUsage.elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
+
+ final String s = in.readUTF();
+
+ myRetentionPolicy = s.length() == 0 ? null : RetentionPolicy.valueOf(s);
+
+ myOuterClassName = in.readInt();
+ myIsLocal = in.readBoolean();
+ myIsAnonymous = in.readBoolean();
+ myUsages =(Set<UsageRepr.Usage>)RW.read(UsageRepr.externalizer(context), new HashSet<UsageRepr.Usage>(), in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ super.save(out);
+ out.writeInt(myFileName);
+ mySuperClass.save(out);
+ RW.save(myInterfaces, out);
+ RW.save(myFields, out);
+ RW.save(myMethods, out);
+ RW.save(myAnnotationTargets, UsageRepr.AnnotationUsage.elementTypeExternalizer, out);
+ out.writeUTF(myRetentionPolicy == null ? "" : myRetentionPolicy.toString());
+ out.writeInt(myOuterClassName);
+ out.writeBoolean(myIsLocal);
+ out.writeBoolean(myIsAnonymous);
+ RW.save(myUsages, UsageRepr.externalizer(myContext), out);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean isAnnotation() {
+ return (access & Opcodes.ACC_ANNOTATION) > 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ClassRepr classRepr = (ClassRepr)o;
+
+ if (myFileName != classRepr.myFileName) return false;
+ if (name != classRepr.name) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * myFileName + name;
+ }
+
+ public UsageRepr.Usage createUsage() {
+ return UsageRepr.createClassUsage(myContext, name);
+ }
+
+ public String getPackageName() {
+ return getPackageName(name);
+ }
+
+ public String getPackageName(final int s) {
+ return getPackageName(myContext.getValue(s));
+ }
+
+ @NotNull
+ public static String getPackageName(final String raw) {
+ final int index = raw.lastIndexOf('/');
+
+ if (index == -1) {
+ return "";
+ }
+
+ return raw.substring(0, index);
+ }
+
+ @Nullable
+ public FieldRepr findField(final int name) {
+ for (FieldRepr f : myFields) {
+ if (f.name == name) {
+ return f;
+ }
+ }
+
+ return null;
+ }
+
+ @NotNull
+ public Collection<MethodRepr> findMethods(final MethodRepr.Predicate p) {
+ final Collection<MethodRepr> result = new LinkedList<MethodRepr>();
+
+ for (MethodRepr mm : myMethods) {
+ if (p.satisfy(mm)) {
+ result.add(mm);
+ }
+ }
+
+ return result;
+ }
+
+ public static DataExternalizer<ClassRepr> externalizer(final DependencyContext context) {
+ return new DataExternalizer<ClassRepr>() {
+ @Override
+ public void save(final DataOutput out, final ClassRepr value) throws IOException {
+ value.save(out);
+ }
+
+ @Override
+ public ClassRepr read(final DataInput in) throws IOException {
+ return new ClassRepr(context, in);
+ }
+ };
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ super.toStream(context, stream);
+
+ stream.print(" Filename : ");
+ stream.println(context.getValue(myFileName));
+
+ stream.print(" Superclass : ");
+ stream.println(mySuperClass == null ? "<null>" : mySuperClass.getDescr(context));
+
+ stream.print(" Interfaces : ");
+ final TypeRepr.AbstractType[] is = myInterfaces.toArray(new TypeRepr.AbstractType[myInterfaces.size()]);
+ Arrays.sort(is, new Comparator<TypeRepr.AbstractType>() {
+ @Override
+ public int compare(final TypeRepr.AbstractType o1, final TypeRepr.AbstractType o2) {
+ return o1.getDescr(context).compareTo(o2.getDescr(context));
+ }
+ });
+ for (final TypeRepr.AbstractType t : is) {
+ stream.print(t.getDescr(context));
+ stream.print(" ");
+ }
+ stream.println();
+
+ stream.print(" Targets : ");
+ final ElemType[] es = myAnnotationTargets.toArray(new ElemType[myAnnotationTargets.size()]);
+ Arrays.sort(es);
+ for (final ElemType e : es) {
+ stream.print(e);
+ stream.print("; ");
+ }
+ stream.println();
+
+ stream.print(" Policy : ");
+ stream.println(myRetentionPolicy);
+
+ stream.print(" Outer class: ");
+ stream.println(context.getValue(myOuterClassName));
+
+ stream.print(" Local class: ");
+ stream.println(myIsLocal);
+ stream.print(" Anonymous class: ");
+ stream.println(myIsAnonymous);
+
+ stream.println(" Fields:");
+ final FieldRepr[] fs = myFields.toArray(new FieldRepr[myFields.size()]);
+ Arrays.sort(fs, new Comparator<FieldRepr>() {
+ @Override
+ public int compare(final FieldRepr o1, final FieldRepr o2) {
+ if (o1.name == o2.name) {
+ return o1.myType.getDescr(context).compareTo(o2.myType.getDescr(context));
+ }
+
+ return context.getValue(o1.name).compareTo(context.getValue(o2.name));
+ }
+ });
+ for (final FieldRepr f : fs) {
+ f.toStream(context, stream);
+ }
+ stream.println(" End Of Fields");
+
+ stream.println(" Methods:");
+ final MethodRepr[] ms = myMethods.toArray(new MethodRepr[myMethods.size()]);
+ Arrays.sort(ms, new Comparator<MethodRepr>() {
+ @Override
+ public int compare(final MethodRepr o1, final MethodRepr o2) {
+ if (o1.name == o2.name) {
+ final String d1 = o1.myType.getDescr(context);
+ final String d2 = o2.myType.getDescr(context);
+
+ final int c = d1.compareTo(d2);
+
+ if (c == 0) {
+ final int l1 = o1.myArgumentTypes.length;
+ final int l2 = o2.myArgumentTypes.length;
+
+ if (l1 == l2) {
+ for (int i = 0; i<l1; i++) {
+ final String d11 = o1.myArgumentTypes[i].getDescr(context);
+ final String d22 = o2.myArgumentTypes[i].getDescr(context);
+
+ final int cc = d11.compareTo(d22);
+
+ if (cc != 0) {
+ return cc;
+ }
+ }
+
+ return 0;
+ }
+
+ return l1 -l2;
+ }
+
+ return c;
+ }
+
+ return context.getValue(o1.name).compareTo(context.getValue(o2.name));
+ }
+ });
+ for (final MethodRepr m : ms) {
+ m.toStream(context, stream);
+ }
+ stream.println(" End Of Methods");
+
+ stream.println(" Usages:");
+
+ final List<String> usages = new LinkedList<String>();
+
+ for (final UsageRepr.Usage u : myUsages) {
+ final ByteArrayOutputStream bas = new ByteArrayOutputStream();
+
+ u.toStream(myContext, new PrintStream(bas));
+
+ try {
+ bas.close();
+ }
+ catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ usages.add(bas.toString());
+ }
+
+ Collections.sort(usages);
+
+ for (final String s : usages) {
+ stream.println(s);
+ }
+
+ stream.println(" End Of Usages");
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java
new file mode 100644
index 000000000000..ebcb39a8fd3b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.Pair;
+import gnu.trove.TIntHashSet;
+import org.jetbrains.asm4.*;
+import org.jetbrains.asm4.signature.SignatureReader;
+import org.jetbrains.asm4.signature.SignatureVisitor;
+
+import java.lang.annotation.RetentionPolicy;
+import java.util.*;
+
+/**
+ * @author: db
+ * Date: 31.01.11
+ */
+
+class ClassfileAnalyzer {
+ private final DependencyContext myContext;
+
+ ClassfileAnalyzer(DependencyContext context) {
+ this.myContext = context;
+ }
+
+ private static class Holder<T> {
+ private T x = null;
+
+ public void set(final T x) {
+ this.x = x;
+ }
+
+ public T get() {
+ return x;
+ }
+ }
+
+ private class ClassCrawler extends ClassVisitor {
+ private class AnnotationRetentionPolicyCrawler extends AnnotationVisitor {
+ private AnnotationRetentionPolicyCrawler() {
+ super(Opcodes.ASM4);
+ }
+
+ public void visit(String name, Object value) {
+ }
+
+ public void visitEnum(String name, String desc, String value) {
+ myRetentionPolicy = RetentionPolicy.valueOf(value);
+ }
+
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ return null;
+ }
+
+ public AnnotationVisitor visitArray(String name) {
+ return null;
+ }
+
+ public void visitEnd() {
+ }
+ }
+
+ private class AnnotationTargetCrawler extends AnnotationVisitor {
+ private AnnotationTargetCrawler() {
+ super(Opcodes.ASM4);
+ }
+
+ public void visit(String name, Object value) {
+ }
+
+ public void visitEnum(final String name, String desc, final String value) {
+ myTargets.add(ElemType.valueOf(value));
+ }
+
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ return this;
+ }
+
+ public AnnotationVisitor visitArray(String name) {
+ return this;
+ }
+
+ public void visitEnd() {
+ }
+ }
+
+ private class AnnotationCrawler extends AnnotationVisitor {
+ private final TypeRepr.ClassType myType;
+ private final ElemType myTarget;
+
+ private final TIntHashSet myUsedArguments = new TIntHashSet();
+
+ private AnnotationCrawler(final TypeRepr.ClassType type, final ElemType target) {
+ super(Opcodes.ASM4);
+ this.myType = type;
+ this.myTarget = target;
+ final Set<ElemType> targets = myAnnotationTargets.get(type);
+ if (targets == null) {
+ myAnnotationTargets.put(type, EnumSet.of(target));
+ }
+ else {
+ targets.add(target);
+ }
+ myUsages.add(UsageRepr.createClassUsage(myContext, type.className));
+ }
+
+ private String getMethodDescr(final Object value) {
+ if (value instanceof Type) {
+ return "()Ljava/lang/Class;";
+ }
+
+ final String name = Type.getType(value.getClass()).getInternalName();
+
+ if (name.equals("java/lang/Integer")) {
+ return "()I;";
+ }
+
+ if (name.equals("java/lang/Short")) {
+ return "()S;";
+ }
+
+ if (name.equals("java/lang/Long")) {
+ return "()J;";
+ }
+
+ if (name.equals("java/lang/Byte")) {
+ return "()B;";
+ }
+
+ if (name.equals("java/lang/Char")) {
+ return "()C;";
+ }
+
+ if (name.equals("java/lang/Boolean")) {
+ return "()Z;";
+ }
+
+ if (name.equals("java/lang/Float")) {
+ return "()F;";
+ }
+
+ if (name.equals("java/lang/Double")) {
+ return "()D;";
+ }
+
+ final String s = "()L" + name + ";";
+
+ return s;
+ }
+
+ public void visit(String name, Object value) {
+ final String methodDescr = getMethodDescr(value);
+ final int methodName = myContext.get(name);
+
+ if (value instanceof Type) {
+ final String className = ((Type)value).getClassName().replace('.', '/');
+
+ if (className != null) {
+ myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(className)));
+ }
+ }
+
+ myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
+ myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
+
+ myUsedArguments.add(methodName);
+ }
+
+ public void visitEnum(String name, String desc, String value) {
+ final int methodName = myContext.get(name);
+ final String methodDescr = "()" + desc;
+
+ myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
+ myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
+
+ myUsedArguments.add(methodName);
+ }
+
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ return new AnnotationCrawler((TypeRepr.ClassType)TypeRepr.getType(myContext, myContext.get(desc)), myTarget);
+ }
+
+ public AnnotationVisitor visitArray(String name) {
+ myUsedArguments.add(myContext.get(name));
+ return this;
+ }
+
+ public void visitEnd() {
+ final TIntHashSet s = myAnnotationArguments.get(myType);
+
+ if (s == null) {
+ myAnnotationArguments.put(myType, myUsedArguments);
+ }
+ else {
+ s.retainAll(myUsedArguments.toArray());
+ }
+ }
+ }
+
+ private void processSignature(final String sig) {
+ if (sig != null) {
+ new SignatureReader(sig).accept(mySignatureCrawler);
+ }
+ }
+
+ private final SignatureVisitor mySignatureCrawler = new SignatureVisitor(Opcodes.ASM4) {
+ public void visitFormalTypeParameter(String name) {
+ return;
+ }
+
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ public SignatureVisitor visitInterfaceBound() {
+ return this;
+ }
+
+ public SignatureVisitor visitSuperclass() {
+ return this;
+ }
+
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ public SignatureVisitor visitParameterType() {
+ return this;
+ }
+
+ public SignatureVisitor visitReturnType() {
+ return this;
+ }
+
+ public SignatureVisitor visitExceptionType() {
+ return this;
+ }
+
+ public void visitBaseType(char descriptor) {
+ return;
+ }
+
+ public void visitTypeVariable(String name) {
+ return;
+ }
+
+ public SignatureVisitor visitArrayType() {
+ return this;
+ }
+
+ public void visitInnerClassType(String name) {
+ return;
+ }
+
+ public void visitTypeArgument() {
+ return;
+ }
+
+ public SignatureVisitor visitTypeArgument(char wildcard) {
+ return this;
+ }
+
+ public void visitEnd() {
+ }
+
+ public void visitClassType(String name) {
+ final int className = myContext.get(name);
+ myUsages.add(UsageRepr.createClassUsage(myContext, className));
+ myUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));
+ }
+ };
+
+ private Boolean myTakeIntoAccount = false;
+
+ private final int myFileName;
+ private int myAccess;
+ private int myName;
+ private String mySuperClass;
+ private String[] myInterfaces;
+ private String mySignature;
+
+ final Holder<String> myClassNameHolder = new Holder<String>();
+ final Holder<String> myOuterClassName = new Holder<String>();
+ final Holder<Boolean> myLocalClassFlag = new Holder<Boolean>();
+ final Holder<Boolean> myAnonymousClassFlag = new Holder<Boolean>();
+
+ {
+ myLocalClassFlag.set(false);
+ myAnonymousClassFlag.set(false);
+ }
+
+ private final Set<MethodRepr> myMethods = new HashSet<MethodRepr>();
+ private final Set<FieldRepr> myFields = new HashSet<FieldRepr>();
+ private final Set<UsageRepr.Usage> myUsages = new HashSet<UsageRepr.Usage>();
+ private final Set<ElemType> myTargets = EnumSet.noneOf(ElemType.class);
+ private RetentionPolicy myRetentionPolicy = null;
+
+ final Map<TypeRepr.ClassType, TIntHashSet> myAnnotationArguments = new HashMap<TypeRepr.ClassType, TIntHashSet>();
+ final Map<TypeRepr.ClassType, Set<ElemType>> myAnnotationTargets = new HashMap<TypeRepr.ClassType, Set<ElemType>>();
+
+ public ClassCrawler(final int fn) {
+ super(Opcodes.ASM4);
+ myFileName = fn;
+ }
+
+ private boolean notPrivate(final int access) {
+ return (access & Opcodes.ACC_PRIVATE) == 0;
+ }
+
+ public Pair<ClassRepr, Set<UsageRepr.Usage>> getResult() {
+ final ClassRepr repr =
+ myTakeIntoAccount ? new ClassRepr(
+ myContext, myAccess, myFileName, myName, myContext.get(mySignature), myContext.get(mySuperClass), myInterfaces,
+ myFields,
+ myMethods, myTargets, myRetentionPolicy, myContext
+ .get(myOuterClassName.get()), myLocalClassFlag.get(), myAnonymousClassFlag.get(), myUsages) : null;
+
+ if (repr != null) {
+ repr.updateClassUsages(myContext, myUsages);
+ }
+
+ return new Pair<ClassRepr, Set<UsageRepr.Usage>>(repr, myUsages);
+ }
+
+ @Override
+ public void visit(int version, int a, String n, String sig, String s, String[] i) {
+ myTakeIntoAccount = notPrivate(a);
+
+ myAccess = a;
+ myName = myContext.get(n);
+ mySignature = sig;
+ mySuperClass = s;
+ myInterfaces = i;
+
+ myClassNameHolder.set(n);
+
+ if (mySuperClass != null) {
+ final int superclassName = myContext.get(mySuperClass);
+ myUsages.add(UsageRepr.createClassUsage(myContext, superclassName));
+ //myUsages.add(UsageRepr.createClassExtendsUsage(myContext, superclassName));
+ }
+
+ if (myInterfaces != null) {
+ for (String it : myInterfaces) {
+ final int interfaceName = myContext.get(it);
+ myUsages.add(UsageRepr.createClassUsage(myContext, interfaceName));
+ //myUsages.add(UsageRepr.createClassExtendsUsage(myContext, interfaceName));
+ }
+ }
+
+ processSignature(sig);
+ }
+
+ @Override
+ public void visitEnd() {
+ for (Map.Entry<TypeRepr.ClassType, Set<ElemType>> entry : myAnnotationTargets.entrySet()) {
+ final TypeRepr.ClassType type = entry.getKey();
+ final Set<ElemType> targets = entry.getValue();
+ final TIntHashSet usedArguments = myAnnotationArguments.get(type);
+
+ myUsages.add(UsageRepr.createAnnotationUsage(myContext, type, usedArguments, targets));
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+ if (desc.equals("Ljava/lang/annotation/Target;")) {
+ return new AnnotationTargetCrawler();
+ }
+
+ if (desc.equals("Ljava/lang/annotation/Retention;")) {
+ return new AnnotationRetentionPolicyCrawler();
+ }
+
+ return new AnnotationCrawler(
+ (TypeRepr.ClassType)TypeRepr.getType(myContext, myContext.get(desc)),
+ (myAccess & Opcodes.ACC_ANNOTATION) > 0 ? ElemType.ANNOTATION_TYPE : ElemType.TYPE
+ );
+ }
+
+ @Override
+ public void visitSource(String source, String debug) {
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String n, String desc, String signature, Object value) {
+ processSignature(signature);
+
+ if ((access & Opcodes.ACC_SYNTHETIC) == 0) {
+ myFields.add(new FieldRepr(myContext, access, myContext.get(n), myContext.get(desc), myContext.get(signature), value));
+ }
+
+ return new FieldVisitor(Opcodes.ASM4) {
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return new AnnotationCrawler((TypeRepr.ClassType)TypeRepr.getType(myContext, myContext.get(desc)), ElemType.FIELD);
+ }
+ };
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String n, final String desc, final String signature, final String[] exceptions) {
+ final Holder<Object> defaultValue = new Holder<Object>();
+
+ processSignature(signature);
+
+ return new MethodVisitor(Opcodes.ASM4) {
+ @Override
+ public void visitEnd() {
+ if ((access & Opcodes.ACC_SYNTHETIC) == 0 || (access & Opcodes.ACC_BRIDGE) > 0) {
+ myMethods.add(new MethodRepr(myContext, access, myContext.get(n), myContext.get(signature), desc, exceptions, defaultValue.get()));
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return new AnnotationCrawler(
+ (TypeRepr.ClassType)TypeRepr.getType(myContext, myContext.get(desc)), "<init>".equals(n) ? ElemType.CONSTRUCTOR : ElemType.METHOD
+ );
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationVisitor(Opcodes.ASM4) {
+ public void visit(String name, Object value) {
+ defaultValue.set(value);
+ }
+ };
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
+ return new AnnotationCrawler((TypeRepr.ClassType)TypeRepr.getType(myContext, myContext.get(desc)), ElemType.PARAMETER);
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ if (cst instanceof Type) {
+ myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(((Type)cst).getInternalName())));
+ }
+
+ super.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ final TypeRepr.ArrayType typ = (TypeRepr.ArrayType)TypeRepr.getType(myContext, myContext.get(desc));
+ final TypeRepr.AbstractType element = typ.getDeepElementType();
+
+ if (element instanceof TypeRepr.ClassType) {
+ final int className = ((TypeRepr.ClassType)element).className;
+ myUsages.add(UsageRepr.createClassUsage(myContext, className));
+ myUsages.add(UsageRepr.createClassNewUsage(myContext, className));
+ }
+
+ typ.updateClassUsages(myContext, myName, myUsages);
+
+ super.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public void visitLocalVariable(String n, String desc, String signature, Label start, Label end, int index) {
+ processSignature(signature);
+ TypeRepr.getType(myContext, myContext.get(desc)).updateClassUsages(myContext, myName, myUsages);
+ super.visitLocalVariable(n, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ if (type != null) {
+ TypeRepr.createClassType(myContext, myContext.get(type)).updateClassUsages(myContext, myName, myUsages);
+ }
+
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ final TypeRepr.AbstractType typ = type.startsWith("[") ? TypeRepr.getType(myContext, myContext.get(type)) : TypeRepr.createClassType(
+ myContext, myContext.get(type));
+
+ if (opcode == Opcodes.NEW) {
+ myUsages.add(UsageRepr.createClassUsage(myContext, ((TypeRepr.ClassType)typ).className));
+ myUsages.add(UsageRepr.createClassNewUsage(myContext, ((TypeRepr.ClassType)typ).className));
+ }
+ else if (opcode == Opcodes.ANEWARRAY) {
+ if (typ instanceof TypeRepr.ClassType) {
+ myUsages.add(UsageRepr.createClassUsage(myContext, ((TypeRepr.ClassType)typ).className));
+ myUsages.add(UsageRepr.createClassNewUsage(myContext, ((TypeRepr.ClassType)typ).className));
+ }
+ }
+
+ typ.updateClassUsages(myContext, myName, myUsages);
+
+ super.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ final int fieldName = myContext.get(name);
+ final int fieldOwner = myContext.get(owner);
+ final int descr = myContext.get(desc);
+
+ if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) {
+ myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr));
+ }
+
+ if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) {
+ addClassUsage(TypeRepr.getType(myContext, descr));
+ }
+
+ myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr));
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ final int methodName = myContext.get(name);
+ final int methodOwner = myContext.get(owner);
+
+ myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc));
+ myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner, desc));
+ addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc)));
+
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ private void addClassUsage(final TypeRepr.AbstractType type) {
+ TypeRepr.ClassType classType = null;
+ if (type instanceof TypeRepr.ClassType) {
+ classType = (TypeRepr.ClassType)type;
+ }
+ else if (type instanceof TypeRepr.ArrayType) {
+ final TypeRepr.AbstractType elemType = ((TypeRepr.ArrayType)type).getDeepElementType();
+ if (elemType instanceof TypeRepr.ClassType) {
+ classType = (TypeRepr.ClassType)elemType;
+ }
+ }
+ if (classType != null) {
+ myUsages.add(UsageRepr.createClassUsage(myContext, classType.className));
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ if (outerName != null) {
+ myOuterClassName.set(outerName);
+ }
+ if (innerName == null) {
+ myAnonymousClassFlag.set(true);
+ }
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String desc) {
+ myOuterClassName.set(owner);
+
+ if (name != null) {
+ myLocalClassFlag.set(true);
+ }
+ }
+ }
+
+ public Pair<ClassRepr, Set<UsageRepr.Usage>> analyze(final int fileName, final ClassReader cr) {
+ final ClassCrawler visitor = new ClassCrawler(fileName);
+
+ cr.accept(visitor, 0);
+
+ return visitor.getResult();
+ }
+} \ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/CollectionFactory.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/CollectionFactory.java
new file mode 100644
index 000000000000..561f2e08f3a0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/CollectionFactory.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import java.util.Collection;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 4/3/12
+*/
+public interface CollectionFactory<X> {
+ Collection<X> create();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java
new file mode 100644
index 000000000000..f79d651fd515
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.io.PersistentStringEnumerator;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: db
+ * Date: 14.02.11
+ */
+class DependencyContext {
+ private final static String STRING_TABLE_NAME = "strings.tab";
+ private final PersistentStringEnumerator myEnumerator;
+
+ private final Map<TypeRepr.AbstractType, TypeRepr.AbstractType> myTypeMap = new HashMap<TypeRepr.AbstractType, TypeRepr.AbstractType>();
+ private final Map<UsageRepr.Usage, UsageRepr.Usage> myUsageMap = new HashMap<UsageRepr.Usage, UsageRepr.Usage>();
+ private final int myEmptyName;
+
+ UsageRepr.Usage getUsage(final UsageRepr.Usage u) {
+ final UsageRepr.Usage r = myUsageMap.get(u);
+
+ if (r == null) {
+ myUsageMap.put(u, u);
+ return u;
+ }
+
+ return r;
+ }
+
+ TypeRepr.AbstractType getType(final TypeRepr.AbstractType t) {
+ final TypeRepr.AbstractType r = myTypeMap.get(t);
+
+ if (r != null) {
+ return r;
+ }
+
+ myTypeMap.put(t, t);
+
+ return t;
+ }
+
+ void clearMemoryCaches() {
+ myTypeMap.clear();
+ myUsageMap.clear();
+ }
+
+ static File getTableFile (final File rootDir, final String name) {
+ final File file = new File(FileUtil.toSystemIndependentName(rootDir.getAbsoluteFile() + File.separator + name));
+ FileUtil.createIfDoesntExist(file);
+ return file;
+ }
+
+ DependencyContext(final File rootDir) throws IOException {
+ final File file = getTableFile(rootDir, STRING_TABLE_NAME);
+ myEnumerator = new PersistentStringEnumerator(file, true);
+ myEmptyName = myEnumerator.enumerate("");
+ }
+
+ @Nullable
+ public String getValue(final int s) {
+ try {
+ return myEnumerator.valueOf(s);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public int get(final String s) {
+ try {
+ return StringUtil.isEmpty(s) ? myEmptyName : myEnumerator.enumerate(s);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void close() {
+ try {
+ myEnumerator.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush() {
+ myEnumerator.force();
+ }
+
+ public Logger<Integer> getLogger(final com.intellij.openapi.diagnostic.Logger log) {
+ return new Logger<Integer>() {
+ @Override
+ public void debug(String comment, Integer s) {
+ if (log.isDebugEnabled()) {
+ log.debug(comment + getValue(s));
+ }
+ }
+
+ @Override
+ public void debug(String comment, String t) {
+ if (log.isDebugEnabled()){
+ log.debug(comment + t);
+ }
+ }
+
+ @Override
+ public void debug(String comment, boolean t) {
+ if (log.isDebugEnabled()) {
+ log.debug(comment + Boolean.toString(t));
+ }
+ }
+ };
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java
new file mode 100644
index 000000000000..0c59a0d0789a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.*;
+
+/**
+ * @author: db
+ * Date: 01.03.11
+ */
+abstract class Difference {
+ public static boolean isPackageLocal(final int access) {
+ return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0;
+ }
+
+ public static boolean weakerAccess(final int me, final int then) {
+ return ((me & Opcodes.ACC_PRIVATE) > 0 && (then & Opcodes.ACC_PRIVATE) == 0) ||
+ ((me & Opcodes.ACC_PROTECTED) > 0 && (then & Opcodes.ACC_PUBLIC) > 0) ||
+ (isPackageLocal(me) && (then & Opcodes.ACC_PROTECTED) > 0);
+ }
+
+ public static final int NONE = 0;
+ public static final int ACCESS = 1;
+ public static final int TYPE = 2;
+ public static final int VALUE = 4;
+ public static final int SIGNATURE = 8;
+ public static final int SUPERCLASS = 16;
+ public static final int USAGES = 32;
+
+ public interface Specifier<T> {
+ Collection<T> added();
+
+ Collection<T> removed();
+
+ Collection<Pair<T, Difference>> changed();
+
+ boolean unchanged();
+ }
+
+ public static <T> Specifier<T> make(final Set<T> past, final Set<T> now) {
+ if (past == null) {
+ final Collection<T> _now = Collections.unmodifiableCollection(now);
+ return new Specifier<T>() {
+ public Collection<T> added() {
+ return _now;
+ }
+
+ public Collection<T> removed() {
+ return Collections.emptyList();
+ }
+
+ public Collection<Pair<T, Difference>> changed() {
+ return Collections.emptyList();
+ }
+
+ public boolean unchanged() {
+ return false;
+ }
+ };
+ }
+
+ final Set<T> added = new HashSet<T>(now);
+
+ added.removeAll(past);
+
+ final Set<T> removed = new HashSet<T>(past);
+
+ removed.removeAll(now);
+
+ final Set<Pair<T, Difference>> changed = new HashSet<Pair<T, Difference>>();
+ final Set<T> intersect = new HashSet<T>(past);
+ final Map<T, T> nowMap = new HashMap<T, T>();
+
+ for (T s : now) {
+ if (intersect.contains(s)) {
+ nowMap.put(s, s);
+ }
+ }
+
+ intersect.retainAll(now);
+
+ for (T x : intersect) {
+ final T y = nowMap.get(x);
+
+ if (x instanceof Proto) {
+ final Proto px = (Proto)x;
+ final Proto py = (Proto)y;
+ final Difference diff = py.difference(px);
+
+ if (!diff.no()) {
+ changed.add(new Pair<T, Difference>(x, diff));
+ }
+ }
+ }
+
+ return new Specifier<T>() {
+ public Collection<T> added() {
+ return added;
+ }
+
+ public Collection<T> removed() {
+ return removed;
+ }
+
+ public Collection<Pair<T, Difference>> changed() {
+ return changed;
+ }
+
+ public boolean unchanged() {
+ return changed.isEmpty() && added.isEmpty() && removed.isEmpty();
+ }
+ };
+ }
+
+ public abstract int base();
+
+ public abstract boolean no();
+
+ public abstract boolean weakedAccess();
+
+ public abstract int addedModifiers();
+
+ public abstract int removedModifiers();
+
+ public abstract boolean packageLocalOn();
+
+ public abstract boolean hadValue();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java
new file mode 100644
index 000000000000..9d9b7c652770
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+public enum ElemType {
+ /** Class, interface (including annotation type), or enum declaration */
+ TYPE,
+
+ /** Field declaration (includes enum constants) */
+ FIELD,
+
+ /** Method declaration */
+ METHOD,
+
+ /** Parameter declaration */
+ PARAMETER,
+
+ /** Constructor declaration */
+ CONSTRUCTOR,
+
+ /** Local variable declaration */
+ LOCAL_VARIABLE,
+
+ /** Annotation type declaration */
+ ANNOTATION_TYPE,
+
+ /** Package declaration */
+ PACKAGE
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java
new file mode 100644
index 000000000000..b72e5aa18d5b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.io.DataExternalizer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * @author: db
+ * Date: 01.02.11
+ */
+class FieldRepr extends ProtoMember {
+ public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
+ myType.updateClassUsages(context, owner, s);
+ }
+
+ public FieldRepr(final DependencyContext context, final int a, final int n, final int d, final int s, final Object v) {
+ super(a, s, n, TypeRepr.getType(context, d), v);
+ }
+
+ public FieldRepr(final DependencyContext context, final DataInput in) {
+ super(context, in);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final FieldRepr fieldRepr = (FieldRepr)o;
+
+ return name == fieldRepr.name;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * name;
+ }
+
+ public static DataExternalizer<FieldRepr> externalizer(final DependencyContext context) {
+ return new DataExternalizer<FieldRepr>() {
+ @Override
+ public void save(final DataOutput out, final FieldRepr value) throws IOException {
+ value.save(out);
+ }
+
+ @Override
+ public FieldRepr read(final DataInput in) throws IOException {
+ return new FieldRepr(context, in);
+ }
+ };
+ }
+
+ public UsageRepr.Usage createUsage(final DependencyContext context, final int owner) {
+ return UsageRepr.createFieldUsage(context, name, owner, context.get(myType.getDescr(context)));
+ }
+
+ public UsageRepr.Usage createAssignUsage(final DependencyContext context, final int owner) {
+ return UsageRepr.createFieldAssignUsage(context, name, owner, context.get(myType.getDescr(context)));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMaplet.java
new file mode 100644
index 000000000000..63f03f44d342
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMaplet.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntIntProcedure;
+
+import java.io.PrintStream;
+
+/**
+ * @author: db
+ * Date: 04.11.11
+ */
+abstract class IntIntMaplet implements Streamable {
+ abstract boolean containsKey(final int key);
+
+ abstract int get(final int key);
+
+ abstract void put(final int key, final int value);
+
+ abstract void putAll(IntIntMaplet m);
+
+ abstract void remove(final int key);
+
+ abstract void close();
+
+ abstract void forEachEntry(TIntIntProcedure proc);
+
+ abstract void flush(boolean memoryCachesOnly);
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ final OrderProvider op = new OrderProvider(context);
+
+ forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(final int a, final int b) {
+ op.register(a);
+ return true;
+ }
+ });
+
+ final int[] keys = op.get();
+
+ for (final int a : keys) {
+ final int b = get(a);
+
+ stream.print(" ");
+ stream.print(context.getValue(a));
+ stream.print(" -> ");
+ stream.println(context.getValue(b));
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMultiMaplet.java
new file mode 100644
index 000000000000..2ed7422b72c1
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntMultiMaplet.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntObjectProcedure;
+import gnu.trove.TIntProcedure;
+
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author: db
+ * Date: 03.11.11
+ */
+abstract class IntIntMultiMaplet implements Streamable {
+ abstract boolean containsKey(final int key);
+
+ abstract TIntHashSet get(final int key);
+
+ abstract void put(final int key, final int value);
+
+ abstract void put(final int key, final TIntHashSet value);
+
+ abstract void replace(final int key, final TIntHashSet value);
+
+ abstract void putAll(IntIntMultiMaplet m);
+
+ abstract void replaceAll(IntIntMultiMaplet m);
+
+ abstract void remove(final int key);
+
+ abstract void removeFrom(final int key, final int value);
+
+ abstract void removeAll(final int key, final TIntHashSet values);
+
+ abstract void close();
+
+ abstract void forEachEntry(TIntObjectProcedure<TIntHashSet> proc);
+
+ abstract void flush(boolean memoryCachesOnly);
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ final OrderProvider op = new OrderProvider(context);
+
+ forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(final int a, final TIntHashSet b) {
+ op.register(a);
+ return true;
+ }
+ });
+
+ final int[] keys = op.get();
+
+ for (final int a : keys) {
+ final TIntHashSet b = get(a);
+
+ stream.print(" Key: ");
+ stream.println(context.getValue(a));
+ stream.println(" Values:");
+
+ final List<String> list = new LinkedList<String>();
+
+ b.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int value) {
+ list.add(context.getValue(value));
+ return true;
+ }
+ });
+
+ Collections.sort(list);
+
+ for (final String l : list) {
+ stream.print(" ");
+ stream.println(l);
+ }
+
+ stream.println(" End Of Values");
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java
new file mode 100644
index 000000000000..34883524988a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.TIntIntProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author: db
+ * Date: 05.11.11
+ */
+public class IntIntPersistentMaplet extends IntIntMaplet {
+ private static final Object NULL_OBJ = new Object();
+ private static final int CACHE_SIZE = 512;
+ private final PersistentHashMap<Integer, Integer> myMap;
+ private final SLRUCache<Integer, Object> myCache;
+
+ public IntIntPersistentMaplet(final File file, final KeyDescriptor<Integer> k) {
+ try {
+ myMap = new PersistentHashMap<Integer, Integer>(file, k, new DataExternalizer<Integer>() {
+ @Override
+ public void save(DataOutput out, Integer value) throws IOException {
+ out.writeInt(value);
+ }
+
+ @Override
+ public Integer read(DataInput in) throws IOException {
+ return in.readInt();
+ }
+ });
+ myCache = new SLRUCache<Integer, Object>(CACHE_SIZE, CACHE_SIZE) {
+ @NotNull
+ @Override
+ public Object createValue(Integer key) {
+ try {
+ final Integer v1 = myMap.get(key);
+ return v1 == null? NULL_OBJ : v1;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean containsKey(final int key) {
+ try {
+ return myMap.containsMapping(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int get(final int key) {
+ final Object obj = myCache.get(key);
+ return obj == NULL_OBJ? 0 : (Integer)obj;
+ }
+
+ @Override
+ public void put(final int key, final int value) {
+ try {
+ myCache.remove(key);
+ myMap.put(key, value);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void putAll(final IntIntMaplet m) {
+ m.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int key, int value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void remove(final int key) {
+ try {
+ myCache.remove(key);
+ myMap.remove(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ try {
+ myCache.clear();
+ myMap.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ else {
+ myMap.force();
+ }
+ }
+
+ @Override
+ public void forEachEntry(final TIntIntProcedure proc) {
+ try {
+ myMap.processKeysWithExistingMapping(new Processor<Integer>() {
+ @Override
+ public boolean process(Integer key) {
+ try {
+ final Integer value = myMap.get(key);
+ return value == null? proc.execute(key, -1) : proc.execute(key, value);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
new file mode 100644
index 000000000000..1d724cf10a94
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntObjectProcedure;
+import gnu.trove.TIntProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.*;
+
+/**
+ * @author: db
+ * Date: 08.03.11
+ */
+class IntIntPersistentMultiMaplet extends IntIntMultiMaplet {
+ private static final TIntHashSet NULL_COLLECTION = new TIntHashSet();
+ private static final int CACHE_SIZE = 128;
+ private final PersistentHashMap<Integer, TIntHashSet> myMap;
+ private final SLRUCache<Integer, TIntHashSet> myCache;
+
+ public IntIntPersistentMultiMaplet(final File file, final KeyDescriptor<Integer> keyExternalizer) throws IOException {
+ myMap = new PersistentHashMap<Integer, TIntHashSet>(file, keyExternalizer, new IntSetExternalizer());
+ myCache = new SLRUCache<Integer, TIntHashSet>(CACHE_SIZE, CACHE_SIZE) {
+ @NotNull
+ @Override
+ public TIntHashSet createValue(Integer key) {
+ try {
+ final TIntHashSet collection = myMap.get(key);
+ return collection == null? NULL_COLLECTION : collection;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ @Override
+ public boolean containsKey(final int key) {
+ try {
+ return myMap.containsMapping(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public TIntHashSet get(final int key) {
+ final TIntHashSet collection = myCache.get(key);
+ return collection == NULL_COLLECTION? null : collection;
+ }
+
+ @Override
+ public void replace(int key, TIntHashSet value) {
+ try {
+ myCache.remove(key);
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final int key, final TIntHashSet value) {
+ try {
+ myCache.remove(key);
+ myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
+ public void append(final DataOutput out) throws IOException {
+ final Ref<IOException> exRef = new Ref<IOException>();
+ value.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ try {
+ out.writeInt(value);
+ }
+ catch (IOException e) {
+ exRef.set(e);
+ return false;
+ }
+ return true;
+ }
+ });
+ final IOException exception = exRef.get();
+ if (exception != null) {
+ throw exception;
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final int key, final int value) {
+ try {
+ myCache.remove(key);
+ myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
+ public void append(final DataOutput out) throws IOException {
+ out.writeInt(value);
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void removeAll(int key, TIntHashSet values) {
+ try {
+ final TIntHashSet collection = myCache.get(key);
+
+ if (collection != NULL_COLLECTION) {
+ if (collection.removeAll(values.toArray())) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void removeFrom(final int key, final int value) {
+ try {
+ final TIntHashSet collection = myCache.get(key);
+ if (collection != NULL_COLLECTION) {
+ if (collection.remove(value)) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void remove(final int key) {
+ try {
+ myCache.remove(key);
+ myMap.remove(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void putAll(IntIntMultiMaplet m) {
+ m.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(int key, TIntHashSet value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void replaceAll(IntIntMultiMaplet m) {
+ m.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(int key, TIntHashSet value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ try {
+ myCache.clear();
+ myMap.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ else {
+ myMap.force();
+ }
+ }
+
+ @Override
+ public void forEachEntry(final TIntObjectProcedure<TIntHashSet> procedure) {
+ try {
+ myMap.processKeysWithExistingMapping(new Processor<Integer>() {
+ @Override
+ public boolean process(Integer key) {
+ try {
+ return procedure.execute(key, myMap.get(key));
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static class IntSetExternalizer implements DataExternalizer<TIntHashSet> {
+ @Override
+ public void save(final DataOutput out, final TIntHashSet value) throws IOException {
+ final Ref<IOException> exRef = new Ref<IOException>(null);
+ value.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int elem) {
+ try {
+ out.writeInt(elem);
+ }
+ catch (IOException e) {
+ exRef.set(e);
+ return false;
+ }
+ return true;
+ }
+ });
+ final IOException exception = exRef.get();
+ if (exception != null) {
+ throw exception;
+ }
+ }
+
+ @Override
+ public TIntHashSet read(final DataInput in) throws IOException {
+ final TIntHashSet result = new TIntHashSet();
+ final DataInputStream stream = (DataInputStream)in;
+ while (stream.available() > 0) {
+ result.add(in.readInt());
+ }
+ return result;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMaplet.java
new file mode 100644
index 000000000000..042e477d1477
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMaplet.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntIntHashMap;
+import gnu.trove.TIntIntProcedure;
+
+/**
+ * @author: db
+ * Date: 05.11.11
+ */
+public class IntIntTransientMaplet extends IntIntMaplet {
+ private final TIntIntHashMap myMap = new TIntIntHashMap();
+
+ @Override
+ public boolean containsKey(final int key) {
+ return myMap.containsKey(key);
+ }
+
+ @Override
+ public int get(final int key) {
+ return myMap.get(key);
+ }
+
+ @Override
+ public void put(final int key, final int value) {
+ myMap.put(key, value);
+ }
+
+ @Override
+ public void putAll(final IntIntMaplet m) {
+ m.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int key, int value) {
+ myMap.put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void remove(final int key) {
+ myMap.remove(key);
+ }
+
+ @Override
+ public void close() {
+ myMap.clear();
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ }
+
+ @Override
+ public void forEachEntry(TIntIntProcedure proc) {
+ myMap.forEachEntry(proc);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMultiMaplet.java
new file mode 100644
index 000000000000..9f552a8a21bf
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntTransientMultiMaplet.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+import gnu.trove.TIntProcedure;
+
+/**
+ * @author: db
+ * Date: 08.03.11
+ */
+class IntIntTransientMultiMaplet extends IntIntMultiMaplet {
+ private final TIntObjectHashMap<TIntHashSet> myMap = new TIntObjectHashMap<TIntHashSet>();
+
+
+ @Override
+ public boolean containsKey(final int key) {
+ return myMap.containsKey(key);
+ }
+
+ @Override
+ public TIntHashSet get(final int key) {
+ return myMap.get(key);
+ }
+
+ @Override
+ public void putAll(IntIntMultiMaplet m) {
+ m.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(int key, TIntHashSet values) {
+ put(key, values);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void put(final int key, final TIntHashSet value) {
+ final TIntHashSet x = myMap.get(key);
+ if (x == null) {
+ myMap.put(key, value);
+ }
+ else {
+ value.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ x.add(value);
+ return true;
+ }
+ });
+ }
+ }
+
+ @Override
+ public void replace(int key, TIntHashSet value) {
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+
+ @Override
+ public void put(final int key, final int value) {
+ final TIntHashSet collection = myMap.get(key);
+ if (collection == null) {
+ final TIntHashSet x = new TIntHashSet();
+ x.add(value);
+ myMap.put(key, x);
+ }
+ else {
+ collection.add(value);
+ }
+ }
+
+ @Override
+ public void removeFrom(final int key, final int value) {
+ final TIntHashSet collection = myMap.get(key);
+ if (collection != null) {
+ if (collection.remove(value)) {
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeAll(int key, TIntHashSet values) {
+ final TIntHashSet collection = myMap.get(key);
+ if (collection != null) {
+ values.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ collection.remove(value);
+ return true;
+ }
+ });
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+
+ @Override
+ public void remove(final int key) {
+ myMap.remove(key);
+ }
+
+ @Override
+ public void replaceAll(IntIntMultiMaplet m) {
+ m.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(int key, TIntHashSet value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void forEachEntry(TIntObjectProcedure<TIntHashSet> procedure) {
+ myMap.forEachEntry(procedure);
+ }
+
+ @Override
+ public void close(){
+ myMap.clear(); // free memory
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMaplet.java
new file mode 100644
index 000000000000..ffbd1f49381a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMaplet.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntObjectProcedure;
+
+import java.io.PrintStream;
+
+/**
+ * @author: db
+ * Date: 04.11.11
+ */
+abstract class IntObjectMaplet<V> implements Streamable {
+ abstract boolean containsKey(final int key);
+
+ abstract V get(final int key);
+
+ abstract void put(final int key, final V value);
+
+ abstract void putAll(IntObjectMaplet<V> m);
+
+ abstract void remove(final int key);
+
+ abstract void close();
+
+ abstract void forEachEntry(TIntObjectProcedure<V> proc);
+
+ abstract void flush(boolean memoryCachesOnly);
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ final OrderProvider op = new OrderProvider(context);
+
+ forEachEntry(new TIntObjectProcedure<V>() {
+ @Override
+ public boolean execute(final int a, final V b) {
+ op.register(a);
+ return true;
+ }
+ });
+
+ final int[] keys = op.get();
+
+ for (final int a : keys) {
+ final V b = get(a);
+
+ stream.print(" ");
+ stream.print(context.getValue(a));
+ stream.print(" -> ");
+
+ stream.print(b.toString());
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
new file mode 100644
index 000000000000..b5415cebaf84
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntObjectProcedure;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author: db
+ * Date: 03.11.11
+ */
+abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable {
+ abstract boolean containsKey(final int key);
+
+ abstract Collection<V> get(final int key);
+
+ abstract void put(final int key, final V value);
+
+ abstract void put(final int key, final Collection<V> value);
+
+ abstract void replace(final int key, final Collection<V> value);
+
+ abstract void putAll(IntObjectMultiMaplet<V> m);
+
+ abstract void replaceAll(IntObjectMultiMaplet<V> m);
+
+ abstract void remove(final int key);
+
+ abstract void removeFrom(final int key, final V value);
+
+ abstract void removeAll(final int key, final Collection<V> value);
+
+ abstract void close();
+
+ abstract void forEachEntry(TIntObjectProcedure<Collection<V>> procedure);
+
+ abstract void flush(boolean memoryCachesOnly);
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ final OrderProvider op = new OrderProvider(context);
+
+ forEachEntry(new TIntObjectProcedure<Collection<V>>() {
+ @Override
+ public boolean execute(final int a, final Collection<V> b) {
+ op.register(a);
+ return true;
+ }
+ });
+
+ final int[] keys = op.get();
+
+ for (final int a : keys) {
+ final Collection<V> b = get(a);
+
+ stream.print(" Key: ");
+ stream.println(context.getValue(a));
+ stream.println(" Values:");
+
+ final List<String> list = new LinkedList<String>();
+
+ for (final V value : b) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream s = new PrintStream(baos);
+
+ value.toStream(context, s);
+
+ list.add(baos.toString());
+ }
+
+ Collections.sort(list);
+
+ for (final String l : list) {
+ stream.print(l);
+ }
+
+ stream.println(" End Of Values");
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java
new file mode 100644
index 000000000000..1f4387cd1f4e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.IntInlineKeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.TIntObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/10/12
+ */
+public class IntObjectPersistentMaplet<V> extends IntObjectMaplet<V>{
+
+ private static final Object NULL_OBJ = new Object();
+ private static final int CACHE_SIZE = 512;
+ private final PersistentHashMap<Integer, V> myMap;
+ private final SLRUCache<Integer, Object> myCache;
+
+ public IntObjectPersistentMaplet(final File file, final DataExternalizer<V> externalizer) {
+ try {
+ myMap = new PersistentHashMap<Integer, V>(file, new IntInlineKeyDescriptor(), externalizer);
+ myCache = new SLRUCache<Integer, Object>(CACHE_SIZE, CACHE_SIZE) {
+ @NotNull
+ @Override
+ public Object createValue(Integer key) {
+ try {
+ final V v1 = myMap.get(key);
+ return v1 == null? NULL_OBJ : v1;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean containsKey(final int key) {
+ try {
+ return myMap.containsMapping(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public V get(final int key) {
+ final Object obj = myCache.get(key);
+ return obj == NULL_OBJ? null : (V)obj;
+ }
+
+ @Override
+ public void put(final int key, final V value) {
+ try {
+ myCache.remove(key);
+ myMap.put(key, value);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void putAll(final IntObjectMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<V>() {
+ @Override
+ public boolean execute(int key, V value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void remove(final int key) {
+ try {
+ myCache.remove(key);
+ myMap.remove(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ try {
+ myCache.clear();
+ myMap.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ else {
+ myMap.force();
+ }
+ }
+
+ @Override
+ public void forEachEntry(final TIntObjectProcedure<V> proc) {
+ try {
+ myMap.processKeysWithExistingMapping(new Processor<Integer>() {
+ @Override
+ public boolean process(Integer key) {
+ try {
+ final V value = myMap.get(key);
+ return value == null? proc.execute(key, null) : proc.execute(key, value);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
new file mode 100644
index 000000000000..23cee400c423
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.TIntObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.*;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author: db
+ * Date: 08.03.11
+ */
+class IntObjectPersistentMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+ private static final Collection NULL_COLLECTION = Collections.emptySet();
+ private static final int CACHE_SIZE = 128;
+ private final PersistentHashMap<Integer, Collection<V>> myMap;
+ private final DataExternalizer<V> myValueExternalizer;
+ private final SLRUCache<Integer, Collection> myCache;
+
+ public IntObjectPersistentMultiMaplet(final File file,
+ final KeyDescriptor<Integer> keyExternalizer,
+ final DataExternalizer<V> valueExternalizer,
+ final CollectionFactory<V> collectionFactory) throws IOException {
+ myValueExternalizer = valueExternalizer;
+ myMap = new PersistentHashMap<Integer, Collection<V>>(file, keyExternalizer, new CollectionDataExternalizer<V>(valueExternalizer, collectionFactory));
+ myCache = new SLRUCache<Integer, Collection>(CACHE_SIZE, CACHE_SIZE) {
+ @NotNull
+ @Override
+ public Collection createValue(Integer key) {
+ try {
+ final Collection<V> collection = myMap.get(key);
+ return collection == null? NULL_COLLECTION : collection;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+
+ @Override
+ public boolean containsKey(final int key) {
+ try {
+ return myMap.containsMapping(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Collection<V> get(final int key) {
+ final Collection<V> collection = myCache.get(key);
+ return collection == NULL_COLLECTION? null : collection;
+ }
+
+ @Override
+ public void replace(int key, Collection<V> value) {
+ try {
+ myCache.remove(key);
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final int key, final Collection<V> value) {
+ try {
+ myCache.remove(key);
+ myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
+ public void append(DataOutput out) throws IOException {
+ for (V v : value) {
+ myValueExternalizer.save(out, v);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final int key, final V value) {
+ put(key, Collections.singleton(value));
+ }
+
+ @Override
+ public void removeAll(int key, Collection<V> values) {
+ try {
+ final Collection collection = myCache.get(key);
+
+ if (collection != NULL_COLLECTION) {
+ if (collection.removeAll(values)) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, (Collection<V>)collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void removeFrom(final int key, final V value) {
+ try {
+ final Collection collection = myCache.get(key);
+
+ if (collection != NULL_COLLECTION) {
+ if (collection.remove(value)) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, (Collection<V>)collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void remove(final int key) {
+ try {
+ myCache.remove(key);
+ myMap.remove(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void putAll(IntObjectMultiMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<Collection<V>>() {
+ @Override
+ public boolean execute(int key, Collection<V> value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void replaceAll(IntObjectMultiMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<Collection<V>>() {
+ @Override
+ public boolean execute(int key, Collection<V> value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ try {
+ myCache.clear();
+ myMap.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ else {
+ myMap.force();
+ }
+ }
+
+ @Override
+ public void forEachEntry(final TIntObjectProcedure<Collection<V>> procedure) {
+ try {
+ myMap.processKeysWithExistingMapping(new Processor<Integer>() {
+ @Override
+ public boolean process(Integer key) {
+ try {
+ return procedure.execute(key, myMap.get(key));
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static class CollectionDataExternalizer<V> implements DataExternalizer<Collection<V>> {
+ private final DataExternalizer<V> myElementExternalizer;
+ private final CollectionFactory<V> myCollectionFactory;
+
+ public CollectionDataExternalizer(DataExternalizer<V> elementExternalizer,
+ CollectionFactory<V> collectionFactory) {
+ myElementExternalizer = elementExternalizer;
+ myCollectionFactory = collectionFactory;
+ }
+
+ @Override
+ public void save(final DataOutput out, final Collection<V> value) throws IOException {
+ for (V x : value) {
+ myElementExternalizer.save(out, x);
+ }
+ }
+
+ @Override
+ public Collection<V> read(final DataInput in) throws IOException {
+ final Collection<V> result = myCollectionFactory.create();
+ final DataInputStream stream = (DataInputStream)in;
+ while (stream.available() > 0) {
+ result.add(myElementExternalizer.read(in));
+ }
+ return result;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMaplet.java
new file mode 100644
index 000000000000..f75f2f426571
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMaplet.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/10/12
+ */
+public class IntObjectTransientMaplet<V> extends IntObjectMaplet<V>{
+ private final TIntObjectHashMap<V> myMap = new TIntObjectHashMap<V>();
+ @Override
+ boolean containsKey(int key) {
+ return myMap.containsKey(key);
+ }
+
+ @Override
+ V get(int key) {
+ return myMap.get(key);
+ }
+
+ @Override
+ void put(int key, V value) {
+ myMap.put(key, value);
+ }
+
+ @Override
+ void putAll(IntObjectMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<V>() {
+ @Override
+ public boolean execute(int key, V value) {
+ myMap.put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ void remove(int key) {
+ myMap.remove(key);
+ }
+
+ @Override
+ void close() {
+ myMap.clear();
+ }
+
+ @Override
+ void forEachEntry(TIntObjectProcedure<V> proc) {
+ myMap.forEachEntry(proc);
+ }
+
+ @Override
+ void flush(boolean memoryCachesOnly) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
new file mode 100644
index 000000000000..2f581805a678
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+
+import java.util.Collection;
+
+/**
+ * @author: db
+ * Date: 08.03.11
+ */
+class IntObjectTransientMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+
+ private final TIntObjectHashMap<Collection<V>> myMap = new TIntObjectHashMap<Collection<V>>();
+ private final CollectionFactory<V> myCollectionFactory;
+
+ public IntObjectTransientMultiMaplet(CollectionFactory<V> collectionFactory) {
+ myCollectionFactory = collectionFactory;
+ }
+
+ @Override
+ public boolean containsKey(final int key) {
+ return myMap.containsKey(key);
+ }
+
+ @Override
+ public Collection<V> get(final int key) {
+ return myMap.get(key);
+ }
+
+ @Override
+ public void putAll(IntObjectMultiMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<Collection<V>>() {
+ @Override
+ public boolean execute(int key, Collection<V> value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void put(final int key, final Collection<V> value) {
+ final Collection<V> x = myMap.get(key);
+ if (x == null) {
+ myMap.put(key, value);
+ }
+ else {
+ x.addAll(value);
+ }
+ }
+
+ @Override
+ public void replace(int key, Collection<V> value) {
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+
+ @Override
+ public void put(final int key, final V value) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection == null) {
+ final Collection<V> x = myCollectionFactory.create();
+ x.add(value);
+ myMap.put(key, x);
+ }
+ else {
+ collection.add(value);
+ }
+ }
+
+ @Override
+ public void removeFrom(final int key, final V value) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection != null) {
+ if (collection.remove(value)) {
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeAll(int key, Collection<V> values) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection != null) {
+ if (collection.removeAll(values)) {
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void remove(final int key) {
+ myMap.remove(key);
+ }
+
+ @Override
+ public void replaceAll(IntObjectMultiMaplet<V> m) {
+ m.forEachEntry(new TIntObjectProcedure<Collection<V>>() {
+ @Override
+ public boolean execute(int key, Collection<V> value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void forEachEntry(TIntObjectProcedure<Collection<V>> procedure) {
+ myMap.forEachEntry(procedure);
+ }
+
+ @Override
+ public void close(){
+ myMap.clear(); // free memory
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Logger.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Logger.java
new file mode 100644
index 000000000000..9a91b72bfaf5
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Logger.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+/**
+ * @author: db
+ * Date: 20.01.12
+ */
+public interface Logger<T> {
+ void debug(String comment, T t);
+ void debug(String comment, String t);
+ void debug(String comment, boolean t);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
new file mode 100644
index 000000000000..5c402023c165
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
@@ -0,0 +1,2401 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.IntInlineKeyDescriptor;
+import gnu.trove.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.incremental.storage.FileKeyDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.annotation.RetentionPolicy;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * @author: db
+ * Date: 28.01.11
+ */
+public class Mappings {
+ private final static Logger LOG = Logger.getInstance("#org.jetbrains.ether.dependencyView.Mappings");
+
+ private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab";
+ private final static String CLASS_TO_CLASS = "classToClass.tab";
+ private final static String SOURCE_TO_CLASS = "sourceToClass.tab";
+ private final static String CLASS_TO_SOURCE = "classToSource.tab";
+ private static final IntInlineKeyDescriptor INT_KEY_DESCRIPTOR = new IntInlineKeyDescriptor();
+ private static final int DEFAULT_SET_CAPACITY = 32;
+ private static final float DEFAULT_SET_LOAD_FACTOR = 0.98f;
+ private static final CollectionFactory<ClassRepr> ourClassSetConstructor = new CollectionFactory<ClassRepr>() {
+ public Set<ClassRepr> create() {
+ return new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ }
+ };
+
+ private final boolean myIsDelta;
+ private final boolean myDeltaIsTransient;
+ private boolean myIsDifferentiated = false;
+ private boolean myIsRebuild = false;
+
+ private final TIntHashSet myChangedClasses;
+ private final THashSet<File> myChangedFiles;
+ private final Set<ClassRepr> myDeletedClasses;
+ private final Object myLock;
+ private final File myRootDir;
+
+ private DependencyContext myContext;
+ private final int myInitName;
+ private final int myEmptyName;
+ private final int myObjectClassName;
+ private org.jetbrains.jps.builders.java.dependencyView.Logger<Integer> myDebugS;
+
+ private IntIntMultiMaplet myClassToSubclasses;
+
+ /**
+ key: the name of a class who is used;
+ values: class names that use the class registered as the key
+ */
+ private IntIntMultiMaplet myClassToClassDependency;
+ private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
+ private IntObjectMaplet<File> myClassToSourceFile;
+
+ private IntIntTransientMultiMaplet myRemovedSuperClasses;
+ private IntIntTransientMultiMaplet myAddedSuperClasses;
+
+ @Nullable
+ private Collection<String> myRemovedFiles;
+
+ private Mappings(final Mappings base) throws IOException {
+ myLock = base.myLock;
+ myIsDelta = true;
+ myChangedClasses = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ myChangedFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY);
+ myDeletedClasses = new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ myDeltaIsTransient = base.myDeltaIsTransient;
+ myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "myDelta");
+ myContext = base.myContext;
+ myInitName = myContext.get("<init>");
+ myEmptyName = myContext.get("");
+ myObjectClassName = myContext.get("java/lang/Object");
+ myDebugS = base.myDebugS;
+ createImplementation();
+ }
+
+ public Mappings(final File rootDir, final boolean transientDelta) throws IOException {
+ myLock = new Object();
+ myIsDelta = false;
+ myChangedClasses = null;
+ myChangedFiles = null;
+ myDeletedClasses = null;
+ myDeltaIsTransient = transientDelta;
+ myRootDir = rootDir;
+ createImplementation();
+ myInitName = myContext.get("<init>");
+ myEmptyName = myContext.get("");
+ myObjectClassName = myContext.get("java/lang/Object");
+ }
+
+ private void createImplementation() throws IOException {
+ if (!myIsDelta) {
+ myContext = new DependencyContext(myRootDir);
+ myDebugS = myContext.getLogger(LOG);
+ }
+
+ myRemovedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
+ myAddedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
+
+ if (myIsDelta && myDeltaIsTransient) {
+ myClassToSubclasses = new IntIntTransientMultiMaplet();
+ myClassToClassDependency = new IntIntTransientMultiMaplet();
+ mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
+ myClassToSourceFile = new IntObjectTransientMaplet<File>();
+ }
+ else {
+ if (myIsDelta) {
+ myRootDir.mkdirs();
+ }
+ myClassToSubclasses = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_SUBCLASSES), INT_KEY_DESCRIPTOR);
+ myClassToClassDependency = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_CLASS), INT_KEY_DESCRIPTOR);
+ mySourceFileToClasses = new ObjectObjectPersistentMultiMaplet<File, ClassRepr>(
+ DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
+ ourClassSetConstructor
+ );
+ myClassToSourceFile = new IntObjectPersistentMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), new FileKeyDescriptor());
+ }
+ }
+
+ public Mappings createDelta() {
+ synchronized (myLock) {
+ try {
+ return new Mappings(this);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void compensateRemovedContent(final Collection<File> compiled) {
+ if (compiled != null) {
+ for (final File file : compiled) {
+ if (!mySourceFileToClasses.containsKey(file)) {
+ mySourceFileToClasses.put(file, new HashSet<ClassRepr>());
+ }
+ }
+ }
+ }
+
+ @Nullable
+ private ClassRepr getReprByName(@Nullable File source, final int name) {
+ if (source == null) {
+ source = myClassToSourceFile.get(name);
+ }
+ if (source != null) {
+ final Collection<ClassRepr> reprs = mySourceFileToClasses.get(source);
+
+ if (reprs != null) {
+ for (ClassRepr repr : reprs) {
+ if (repr.name == name) {
+ return repr;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void clean() throws IOException {
+ if (myRootDir != null) {
+ synchronized (myLock) {
+ close();
+ FileUtil.delete(myRootDir);
+ createImplementation();
+ }
+ }
+ }
+
+ public IntIntTransientMultiMaplet getRemovedSuperClasses() {
+ return myRemovedSuperClasses;
+ }
+
+ public IntIntTransientMultiMaplet getAddedSuperClasses() {
+ return myAddedSuperClasses;
+ }
+
+ private final LinkedBlockingQueue<Runnable> myPostPasses = new LinkedBlockingQueue<Runnable>();
+
+ private void runPostPasses() {
+ final Set<ClassRepr> deleted = myDeletedClasses;
+ if (deleted != null) {
+ for (ClassRepr repr : deleted) {
+ myChangedClasses.remove(repr.name);
+ }
+ }
+ for (Runnable pass = myPostPasses.poll(); pass != null; pass = myPostPasses.poll()) {
+ pass.run();
+ }
+ }
+
+ private static final ClassRepr MOCK_CLASS = null;
+ private static final MethodRepr MOCK_METHOD = null;
+
+ private interface MemberComparator {
+ boolean isSame(ProtoMember member);
+ }
+
+ private class Util {
+ @Nullable
+ private final Mappings myMappings;
+
+ private Util() {
+ myMappings = null;
+ }
+
+ private Util(@NotNull Mappings mappings) {
+ myMappings = mappings;
+ }
+
+ void appendDependents(final ClassRepr c, final TIntHashSet result) {
+ final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
+
+ if (depClasses != null) {
+ addAll(result, depClasses);
+ }
+ }
+
+ void propagateMemberAccessRec(final TIntHashSet acc, final boolean isField, final boolean root, final MemberComparator comparator, final int reflcass) {
+ final ClassRepr repr = reprByName(reflcass);
+ if (repr != null) {
+ if (!root) {
+ final Set<? extends ProtoMember> members = isField ? repr.getFields() : repr.getMethods();
+
+ for (ProtoMember m : members) {
+ if (comparator.isSame(m)) {
+ return;
+ }
+ }
+
+ acc.add(reflcass);
+ }
+
+ final TIntHashSet subclasses = myClassToSubclasses.get(reflcass);
+
+ if (subclasses != null) {
+ subclasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subclass) {
+ propagateMemberAccessRec(acc, isField, false, comparator, subclass);
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+ TIntHashSet propagateMemberAccess(final boolean isField, final MemberComparator comparator, final int className) {
+ final TIntHashSet acc = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ propagateMemberAccessRec(acc, isField, true, comparator, className);
+ return acc;
+ }
+
+ TIntHashSet propagateFieldAccess(final int name, final int className) {
+ return propagateMemberAccess(true, new MemberComparator() {
+ @Override
+ public boolean isSame(ProtoMember member) {
+ return member.name == name;
+ }
+ }, className);
+ }
+
+ TIntHashSet propagateMethodAccess(final MethodRepr m, final int className) {
+ return propagateMemberAccess(false, new MemberComparator() {
+ @Override
+ public boolean isSame(ProtoMember member) {
+ if (member instanceof MethodRepr) {
+ final MethodRepr memberMethod = (MethodRepr)member;
+ return memberMethod.name == m.name && Arrays.equals(memberMethod.myArgumentTypes, m.myArgumentTypes);
+ }
+ return member.name == m.name;
+ }
+ }, className);
+ }
+
+ MethodRepr.Predicate lessSpecific(final MethodRepr than) {
+ return new MethodRepr.Predicate() {
+ @Override
+ public boolean satisfy(final MethodRepr m) {
+ if (m.name == myInitName || m.name != than.name || m.myArgumentTypes.length != than.myArgumentTypes.length) {
+ return false;
+ }
+
+ for (int i = 0; i < than.myArgumentTypes.length; i++) {
+ final Boolean subtypeOf = isSubtypeOf(than.myArgumentTypes[i], m.myArgumentTypes[i]);
+ if (subtypeOf != null && !subtypeOf) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+ }
+
+ private void addOverridingMethods(final MethodRepr m, final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection<Pair<MethodRepr, ClassRepr>> container) {
+ final TIntHashSet subClasses = myClassToSubclasses.get(fromClass.name);
+ if (subClasses == null) {
+ return;
+ }
+ subClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subClassName) {
+ final ClassRepr r = reprByName(subClassName);
+
+ if (r != null) {
+ boolean cont = true;
+ final Collection<MethodRepr> methods = r.findMethods(predicate);
+ for (MethodRepr mm : methods) {
+ if (isVisibleIn(fromClass, m, r)) {
+ container.add(new Pair<MethodRepr, ClassRepr>(mm, r));
+ cont = false;
+ }
+ }
+ if (cont) {
+ addOverridingMethods(m, r, predicate, container);
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ private Collection<Pair<MethodRepr, ClassRepr>> findAllMethodsBySpecificity(final MethodRepr m, final ClassRepr c) {
+ final MethodRepr.Predicate predicate = lessSpecific(m);
+ final Collection<Pair<MethodRepr, ClassRepr>> result = new HashSet<Pair<MethodRepr, ClassRepr>>();
+ addOverridenMethods(c, predicate, result);
+ addOverridingMethods(m, c, predicate, result);
+ return result;
+ }
+
+ private Collection<Pair<MethodRepr, ClassRepr>> findOverriddenMethods(final MethodRepr m, final ClassRepr c) {
+ final Collection<Pair<MethodRepr, ClassRepr>> result = new HashSet<Pair<MethodRepr, ClassRepr>>();
+ addOverridenMethods(c, MethodRepr.equalByJavaRules(m), result);
+ return result;
+ }
+
+ private boolean hasOverriddenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate) {
+ for (int superName : fromClass.getSupers()) {
+ final ClassRepr superClass = reprByName(superName);
+ if (superClass == null) {
+ return true; // assumption
+ }
+ for (MethodRepr mm : superClass.findMethods(predicate)) {
+ if (isVisibleIn(superClass, mm, fromClass)) {
+ return true;
+ }
+ }
+ if (hasOverriddenMethods(superClass, predicate)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addOverridenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection<Pair<MethodRepr, ClassRepr>> container) {
+ for (int superName : fromClass.getSupers()) {
+ final ClassRepr superClass = reprByName(superName);
+ if (superClass != null) {
+ boolean cont = true;
+ final Collection<MethodRepr> methods = superClass.findMethods(predicate);
+ for (MethodRepr mm : methods) {
+ if (isVisibleIn(superClass, mm, fromClass)) {
+ container.add(new Pair<MethodRepr, ClassRepr>(mm, superClass));
+ cont = false;
+ }
+ }
+ if (cont) {
+ addOverridenMethods(superClass, predicate, container);
+ }
+ }
+ else {
+ container.add(new Pair<MethodRepr, ClassRepr>(MOCK_METHOD, MOCK_CLASS));
+ }
+ }
+ }
+
+ void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
+ for (int supername : fromClass.getSupers()) {
+ final ClassRepr superClass = reprByName(supername);
+ if (superClass != null) {
+ final FieldRepr ff = superClass.findField(f.name);
+ if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
+ container.add(new Pair<FieldRepr, ClassRepr>(ff, superClass));
+ }
+ else{
+ addOverriddenFields(f, superClass, container);
+ }
+ }
+ }
+ }
+
+ boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
+ for (int supername : fromClass.getSupers()) {
+ final ClassRepr superClass = reprByName(supername);
+ if (superClass != null) {
+ final FieldRepr ff = superClass.findField(f.name);
+ if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
+ return true;
+ }
+ final boolean found = hasOverriddenFields(f, superClass);
+ if (found) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ ClassRepr reprByName(final int name) {
+ if (myMappings != null) {
+ final ClassRepr r = myMappings.getReprByName(null, name);
+
+ if (r != null) {
+ return r;
+ }
+ }
+
+ return getReprByName(null, name);
+ }
+
+ @Nullable
+ private Boolean isInheritorOf(final int who, final int whom) {
+ if (who == whom) {
+ return Boolean.TRUE;
+ }
+
+ final ClassRepr repr = reprByName(who);
+
+ if (repr != null) {
+ for (int s : repr.getSupers()) {
+ final Boolean inheritorOf = isInheritorOf(s, whom);
+ if (inheritorOf != null && inheritorOf) {
+ return inheritorOf;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ Boolean isSubtypeOf(final TypeRepr.AbstractType who, final TypeRepr.AbstractType whom) {
+ if (who.equals(whom)) {
+ return Boolean.TRUE;
+ }
+
+ if (who instanceof TypeRepr.PrimitiveType || whom instanceof TypeRepr.PrimitiveType) {
+ return Boolean.FALSE;
+ }
+
+ if (who instanceof TypeRepr.ArrayType) {
+ if (whom instanceof TypeRepr.ArrayType) {
+ return isSubtypeOf(((TypeRepr.ArrayType)who).elementType, ((TypeRepr.ArrayType)whom).elementType);
+ }
+
+ final String descr = whom.getDescr(myContext);
+
+ if (descr.equals("Ljava/lang/Cloneable") || descr.equals("Ljava/lang/Object") || descr.equals("Ljava/io/Serializable")) {
+ return Boolean.TRUE;
+ }
+
+ return Boolean.FALSE;
+ }
+
+ if (whom instanceof TypeRepr.ClassType) {
+ return isInheritorOf(((TypeRepr.ClassType)who).className, ((TypeRepr.ClassType)whom).className);
+ }
+
+ return Boolean.FALSE;
+ }
+
+ boolean isMethodVisible(final int className, final MethodRepr m) {
+ final ClassRepr r = reprByName(className);
+ if (r != null) {
+ if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) {
+ return true;
+ }
+ return hasOverriddenMethods(r, MethodRepr.equalByJavaRules(m));
+ }
+ return false;
+ }
+
+ boolean isFieldVisible(final int className, final FieldRepr field) {
+ final ClassRepr r = reprByName(className);
+ if (r == null || r.getFields().contains(field)) {
+ return true;
+ }
+ return hasOverriddenFields(field, r);
+ }
+
+ void collectSupersRecursively(@NotNull final int className, @NotNull final TIntHashSet container) {
+ final ClassRepr classRepr = reprByName(className);
+ if (classRepr != null) {
+ final int[] supers = classRepr.getSupers();
+ container.addAll(supers);
+ for (int aSuper : supers) {
+ collectSupersRecursively(aSuper, container);
+ }
+ }
+ }
+
+ void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages) {
+ debug("Affecting subclasses of class: ", className);
+
+ final File fileName = myClassToSourceFile.get(className);
+ if (fileName == null) {
+ debug("No source file detected for class ", className);
+ debug("End of affectSubclasses");
+ return;
+ }
+
+ debug("Source file name: ", fileName);
+
+ if (usages) {
+ debug("Class usages affection requested");
+
+ final ClassRepr classRepr = reprByName(className);
+ if (classRepr != null) {
+ debug("Added class usage for ", classRepr.name);
+ affectedUsages.add(classRepr.createUsage());
+ }
+ }
+
+ final TIntHashSet depClasses = myClassToClassDependency.get(className);
+ if (depClasses != null) {
+ addAll(dependants, depClasses);
+ }
+ affectedFiles.add(fileName);
+
+ final TIntHashSet directSubclasses = myClassToSubclasses.get(className);
+ if (directSubclasses != null) {
+ directSubclasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subClass) {
+ affectSubclasses(subClass, affectedFiles, affectedUsages, dependants, usages);
+ return true;
+ }
+ });
+ }
+ }
+
+ void affectFieldUsages(final FieldRepr field, final TIntHashSet classes, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
+ affectedUsages.add(rootUsage);
+
+ classes.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int p) {
+ final TIntHashSet deps = myClassToClassDependency.get(p);
+ if (deps != null) {
+ addAll(dependents, deps);
+ }
+ debug("Affect field usage referenced of class ", p);
+ affectedUsages.add(rootUsage instanceof UsageRepr.FieldAssignUsage ? field.createAssignUsage(myContext, p) : field.createUsage(myContext, p));
+ return true;
+ }
+ });
+ }
+
+ void affectMethodUsages(final MethodRepr method, final TIntHashSet subclasses, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
+ affectedUsages.add(rootUsage);
+ if (subclasses != null) {
+ subclasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int p) {
+ final TIntHashSet deps = myClassToClassDependency.get(p);
+ if (deps != null) {
+ addAll(dependents, deps);
+ }
+
+ debug("Affect method usage referenced of class ", p);
+
+ final UsageRepr.Usage usage =
+ rootUsage instanceof UsageRepr.MetaMethodUsage ? method.createMetaUsage(myContext, p) : method.createUsage(myContext, p);
+ affectedUsages.add(usage);
+ return true;
+ }
+ });
+ }
+ }
+
+ public abstract class UsageConstraint {
+ public abstract boolean checkResidence(final int residence);
+ }
+
+ public class PackageConstraint extends UsageConstraint {
+ public final String packageName;
+
+ public PackageConstraint(final String packageName) {
+ this.packageName = packageName;
+ }
+
+ @Override
+ public boolean checkResidence(final int residence) {
+ return !ClassRepr.getPackageName(myContext.getValue(residence)).equals(packageName);
+ }
+ }
+
+ public class InheritanceConstraint extends PackageConstraint {
+ public final int rootClass;
+
+ public InheritanceConstraint(final int rootClass) {
+ super(ClassRepr.getPackageName(myContext.getValue(rootClass)));
+ this.rootClass = rootClass;
+ }
+
+ @Override
+ public boolean checkResidence(final int residence) {
+ final Boolean inheritorOf = isInheritorOf(residence, rootClass);
+ return inheritorOf == null || !inheritorOf || super.checkResidence(residence);
+ }
+ }
+
+ public class NegationConstraint extends UsageConstraint {
+ final UsageConstraint x;
+
+ public NegationConstraint(UsageConstraint x) {
+ this.x = x;
+ }
+
+ @Override
+ public boolean checkResidence(final int residence) {
+ return !x.checkResidence(residence);
+ }
+ }
+
+ public class IntersectionConstraint extends UsageConstraint {
+ final UsageConstraint x;
+ final UsageConstraint y;
+
+ public IntersectionConstraint(final UsageConstraint x, final UsageConstraint y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public boolean checkResidence(final int residence) {
+ return x.checkResidence(residence) && y.checkResidence(residence);
+ }
+ }
+ }
+
+ void affectAll(final int className, final Collection<File> affectedFiles, @Nullable final DependentFilesFilter filter) {
+ final File sourceFile = myClassToSourceFile.get(className);
+ if (sourceFile != null) {
+ final TIntHashSet dependants = myClassToClassDependency.get(className);
+ if (dependants != null) {
+ dependants.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int depClass) {
+ final File depFile = myClassToSourceFile.get(depClass);
+ if (depFile != null && !FileUtil.filesEqual(depFile, sourceFile)) {
+ if (filter == null || filter.accept(depFile)) {
+ affectedFiles.add(depFile);
+ }
+ }
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+ private static boolean isVisibleIn(final ClassRepr c, final ProtoMember m, final ClassRepr scope) {
+ final boolean privacy = ((m.access & Opcodes.ACC_PRIVATE) > 0) && c.name != scope.name;
+ final boolean packageLocality = Difference.isPackageLocal(m.access) && !c.getPackageName().equals(scope.getPackageName());
+ return !privacy && !packageLocality;
+ }
+
+ private boolean isEmpty(final int s) {
+ return s == myEmptyName;
+ }
+
+ @NotNull
+ private TIntHashSet getAllSubclasses(final int root) {
+ return addAllSubclasses(root, new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR));
+ }
+
+ private TIntHashSet addAllSubclasses(final int root, final TIntHashSet acc) {
+ final TIntHashSet directSubclasses = myClassToSubclasses.get(root);
+
+ acc.add(root);
+
+ if (directSubclasses != null) {
+ directSubclasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int s) {
+ if (!acc.contains(s)) {
+ addAllSubclasses(s, acc);
+ }
+ return true;
+ }
+ });
+ }
+ return acc;
+ }
+
+ private boolean incrementalDecision(final int owner, final Proto member, final Collection<File> affectedFiles, @Nullable final DependentFilesFilter filter) {
+ final boolean isField = member instanceof FieldRepr;
+ final Util self = new Util();
+
+ // Public branch --- hopeless
+ if ((member.access & Opcodes.ACC_PUBLIC) > 0) {
+ debug("Public access, switching to a non-incremental mode");
+ return false;
+ }
+
+ // Protected branch
+ if ((member.access & Opcodes.ACC_PROTECTED) > 0) {
+ debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
+ debug("Root class: ", owner);
+
+ final TIntHashSet propagated = self.propagateFieldAccess(isField ? member.name : myEmptyName, owner);
+ propagated.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int className) {
+ final File fileName = myClassToSourceFile.get(className);
+ if (fileName != null) {
+ debug("Adding ", fileName);
+ affectedFiles.add(fileName);
+ }
+ return true;
+ }
+ });
+ }
+
+ final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name));
+
+ debug("Softening non-incremental decision: adding all package classes for a recompilation");
+ debug("Package name: ", packageName);
+
+ // Package-local branch
+ myClassToSourceFile.forEachEntry(new TIntObjectProcedure<File>() {
+ @Override
+ public boolean execute(int className, File fileName) {
+ if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
+ if (filter == null || filter.accept(fileName)) {
+ debug("Adding: ", fileName);
+ affectedFiles.add(fileName);
+ }
+ }
+ return true;
+ }
+ });
+
+ return true;
+ }
+
+ public interface DependentFilesFilter {
+ DependentFilesFilter ALL_FILES = new DependentFilesFilter() {
+ @Override
+ public boolean accept(File file) {
+ return true;
+ }
+ };
+
+ boolean accept(File file);
+ }
+
+ private class Differential {
+ private static final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
+
+ final Mappings myDelta;
+ final Collection<File> myFilesToCompile;
+ final Collection<File> myCompiledFiles;
+ final Collection<File> myAffectedFiles;
+ @Nullable
+ final DependentFilesFilter myFilter;
+ @Nullable final Callbacks.ConstantAffectionResolver myConstantSearch;
+ final DelayedWorks myDelayedWorks;
+
+ final Util myFuture;
+ final Util myPresent;
+
+ final boolean myEasyMode; // true means: no need to search for affected files, only preprocess data for integrate
+
+ private class DelayedWorks {
+ class Triple {
+ final int owner;
+ final FieldRepr field;
+ @Nullable
+ final Future<Callbacks.ConstantAffection> affection;
+
+ private Triple(final int owner, final FieldRepr field, @Nullable final Future<Callbacks.ConstantAffection> affection) {
+ this.owner = owner;
+ this.field = field;
+ this.affection = affection;
+ }
+
+ Callbacks.ConstantAffection getAffection() {
+ try {
+ return affection != null ? affection.get() : Callbacks.ConstantAffection.EMPTY;
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ final Collection<Triple> myQueue = new LinkedList<Triple>();
+
+ void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) {
+ final Future<Callbacks.ConstantAffection> future;
+ if (myConstantSearch == null) {
+ future = null;
+ }
+ else {
+ final String className = myContext.getValue(ownerClass);
+ final String fieldName = myContext.getValue(changedField.name);
+ future = myConstantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged);
+ }
+ myQueue.add(new Triple(ownerClass, changedField, future));
+ }
+
+ boolean doWork(@NotNull final Collection<File> affectedFiles) {
+ if (!myQueue.isEmpty()) {
+ debug("Starting delayed works.");
+
+ for (final Triple t : myQueue) {
+ final Callbacks.ConstantAffection affection = t.getAffection();
+
+ debug("Class: ", t.owner);
+ debug("Field: ", t.field.name);
+
+ if (!affection.isKnown()) {
+ if (myConstantSearch != null) {
+ debug("No external dependency information available.");
+ }
+ else {
+ debug("Constant search service not available.");
+ }
+ debug("Trying to soften non-incremental decision.");
+ if (!incrementalDecision(t.owner, t.field, affectedFiles, myFilter)) {
+ debug("No luck.");
+ debug("End of delayed work, returning false.");
+ return false;
+ }
+ }
+ else {
+ debug("External dependency information retrieved.");
+ final Collection<File> files = affection.getAffectedFiles();
+ if (myFilter == null) {
+ affectedFiles.addAll(files);
+ }
+ else {
+ for (File file : files) {
+ if (myFilter.accept(file)) {
+ affectedFiles.add(file);
+ }
+ }
+ }
+ }
+ }
+
+ debug("End of delayed work, returning true.");
+ }
+ return true;
+ }
+ }
+
+ private class FileClasses {
+ final File myFileName;
+ final Set<ClassRepr> myFileClasses;
+
+ FileClasses(File fileName, Collection<ClassRepr> fileClasses) {
+ this.myFileName = fileName;
+ this.myFileClasses = new HashSet<ClassRepr>(fileClasses);
+ }
+ }
+
+ private class DiffState {
+ final public TIntHashSet myDependants = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+
+ final public Set<UsageRepr.Usage> myAffectedUsages = new HashSet<UsageRepr.Usage>();
+ final public Set<UsageRepr.AnnotationUsage> myAnnotationQuery = new HashSet<UsageRepr.AnnotationUsage>();
+ final public Map<UsageRepr.Usage, Util.UsageConstraint> myUsageConstraints = new HashMap<UsageRepr.Usage, Util.UsageConstraint>();
+
+ final Difference.Specifier<ClassRepr> myClassDiff;
+
+ private DiffState(Difference.Specifier<ClassRepr> classDiff) {
+ this.myClassDiff = classDiff;
+ }
+ }
+
+ private Differential(final Mappings delta) {
+ this.myDelta = delta;
+ this.myFilesToCompile = null;
+ this.myCompiledFiles = null;
+ this.myAffectedFiles = null;
+ this.myFilter = null;
+ this.myConstantSearch = null;
+
+ myDelayedWorks = null;
+
+ myFuture = null;
+ myPresent = null;
+
+ myEasyMode = true;
+
+ delta.myIsRebuild = true;
+ }
+
+ private Differential(final Mappings delta, final Collection<String> removed, final Collection<File> filesToCompile) {
+ delta.myRemovedFiles = removed;
+
+ this.myDelta = delta;
+ this.myFilesToCompile = filesToCompile;
+ this.myCompiledFiles = null;
+ this.myAffectedFiles = null;
+ this.myFilter = null;
+ this.myConstantSearch = null;
+
+ myDelayedWorks = null;
+
+ myFuture = new Util(delta);
+ myPresent = new Util();
+ myEasyMode = true;
+ }
+
+ private Differential(final Mappings delta,
+ final Collection<String> removed,
+ final Collection<File> filesToCompile,
+ final Collection<File> compiledFiles,
+ final Collection<File> affectedFiles,
+ final DependentFilesFilter filter,
+ @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
+ delta.myRemovedFiles = removed;
+
+ this.myDelta = delta;
+ this.myFilesToCompile = filesToCompile;
+ this.myCompiledFiles = compiledFiles;
+ this.myAffectedFiles = affectedFiles;
+ this.myFilter = filter;
+ this.myConstantSearch = constantSearch;
+
+ myDelayedWorks = new DelayedWorks();
+
+ myFuture = new Util(delta);
+ myPresent = new Util();
+
+ myEasyMode = false;
+ }
+
+ private void processDisappearedClasses() {
+ myDelta.compensateRemovedContent(myFilesToCompile);
+
+ if (!myEasyMode) {
+ final Collection<String> removed = myDelta.myRemovedFiles;
+
+ if (removed != null) {
+ for (final String file : removed) {
+ final Collection<ClassRepr> classes = mySourceFileToClasses.get(new File(file));
+
+ if (classes != null) {
+ for (ClassRepr c : classes) {
+ debug("Affecting usages of removed class ", c.name);
+ affectAll(c.name, myAffectedFiles, myFilter);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void processAddedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ final Collection<MethodRepr> added = diff.methods().added();
+ if (added.isEmpty()) {
+ return;
+ }
+ debug("Processing added methods: ");
+ if (it.isAnnotation()) {
+ debug("Class is annotation, skipping method analysis");
+ return;
+ }
+ Ref<ClassRepr> oldItRef = null;
+ for (final MethodRepr m : added) {
+ debug("Method: ", m.name);
+ if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
+ (it.access & Opcodes.ACC_ABSTRACT) > 0 ||
+ (m.access & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
+ myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false);
+ }
+
+ TIntHashSet propagated = null;
+
+ if ((m.access & Opcodes.ACC_PRIVATE) == 0 && m.name != myInitName) {
+ if (oldItRef == null) {
+ oldItRef = new Ref<ClassRepr>(getReprByName(null, it.name)); // lazy init
+ }
+ final ClassRepr oldIt = oldItRef.get();
+
+ if (oldIt != null && myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {
+
+ }
+ else {
+ if (m.myArgumentTypes.length > 0) {
+ propagated = myFuture.propagateMethodAccess(m, it.name);
+ debug("Conservative case on overriding methods, affecting method usages");
+ myFuture.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ }
+ }
+
+ if ((m.access & Opcodes.ACC_PRIVATE) == 0) {
+ final Collection<Pair<MethodRepr, ClassRepr>> affectedMethods = myFuture.findAllMethodsBySpecificity(m, it);
+ final MethodRepr.Predicate overrides = MethodRepr.equalByJavaRules(m);
+
+ if (propagated == null) {
+ propagated = myFuture.propagateMethodAccess(m, it.name);
+ }
+
+ final Collection<MethodRepr> lessSpecific = it.findMethods(myFuture.lessSpecific(m));
+
+ for (final MethodRepr mm : lessSpecific) {
+ if (!mm.equals(m)) {
+ debug("Found less specific method, affecting method usages");
+ myFuture.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ }
+
+ debug("Processing affected by specificity methods");
+ for (final Pair<MethodRepr, ClassRepr> pair : affectedMethods) {
+ final MethodRepr method = pair.first;
+ final ClassRepr methodClass = pair.second;
+
+ if (methodClass == MOCK_CLASS) {
+ continue;
+ }
+ final Boolean inheritorOf = myPresent.isInheritorOf(methodClass.name, it.name);
+ final boolean isInheritor = inheritorOf != null && inheritorOf;
+
+ debug("Method: ", method.name);
+ debug("Class : ", methodClass.name);
+
+ if (overrides.satisfy(method) && isInheritor) {
+ debug("Current method overrides that found");
+
+ final File file = myClassToSourceFile.get(methodClass.name);
+
+ if (file != null) {
+ myAffectedFiles.add(file);
+ debug("Affecting file ", file);
+ }
+ }
+ else {
+ debug("Current method does not override that found");
+
+ final TIntHashSet yetPropagated = myPresent.propagateMethodAccess(method, it.name);
+
+ if (isInheritor) {
+ final TIntHashSet deps = myClassToClassDependency.get(methodClass.name);
+
+ if (deps != null) {
+ addAll(state.myDependants, deps);
+ }
+
+ myFuture.affectMethodUsages(method, yetPropagated, method.createUsage(myContext, methodClass.name), state.myAffectedUsages,
+ state.myDependants);
+ }
+
+ debug("Affecting method usages for that found");
+ myFuture.affectMethodUsages(method, yetPropagated, method.createUsage(myContext, it.name), state.myAffectedUsages,
+ state.myDependants);
+ }
+ }
+
+ final TIntHashSet subClasses = getAllSubclasses(it.name);
+
+ if (subClasses != null) {
+ subClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subClass) {
+ final ClassRepr r = myFuture.reprByName(subClass);
+ if (r != null) {
+ final File sourceFileName = myClassToSourceFile.get(subClass);
+ if (sourceFileName != null) {
+ final int outerClass = r.getOuterClassName();
+ if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
+ myAffectedFiles.add(sourceFileName);
+ debug("Affecting file due to local overriding: ", sourceFileName);
+ }
+ }
+ }
+ return true;
+ }
+ });
+ }
+ }
+ }
+ debug("End of added methods processing");
+ }
+
+ private void processRemovedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ final Collection<MethodRepr> removed = diff.methods().removed();
+ if (removed.isEmpty()) {
+ return;
+ }
+ debug("Processing removed methods:");
+ for (final MethodRepr m : removed) {
+ debug("Method ", m.name);
+
+ final Collection<Pair<MethodRepr, ClassRepr>> overridenMethods = myFuture.findOverriddenMethods(m, it);
+ final TIntHashSet propagated = myFuture.propagateMethodAccess(m, it.name);
+
+ if (overridenMethods.size() == 0) {
+ debug("No overridden methods found, affecting method usages");
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ else {
+ boolean clear = true;
+
+ loop:
+ for (final Pair<MethodRepr, ClassRepr> overriden : overridenMethods) {
+ final MethodRepr mm = overriden.first;
+
+ if (mm == MOCK_METHOD || !mm.myType.equals(m.myType) || !isEmpty(mm.signature) || !isEmpty(m.signature)) {
+ clear = false;
+ break loop;
+ }
+ }
+
+ if (!clear) {
+ debug("No clearly overridden methods found, affecting method usages");
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ }
+
+ final Collection<Pair<MethodRepr, ClassRepr>> overridingMethods = new HashSet<Pair<MethodRepr, ClassRepr>>();
+
+ myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);
+
+ for (final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
+ final File fName = myClassToSourceFile.get(p.second.name);
+ if (fName != null) {
+ myAffectedFiles.add(fName);
+ debug("Affecting file by overriding: ", fName);
+ }
+ }
+
+ if ((m.access & Opcodes.ACC_ABSTRACT) == 0) {
+ propagated.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int p) {
+ if (p != it.name) {
+ final ClassRepr s = myFuture.reprByName(p);
+
+ if (s != null) {
+ final Collection<Pair<MethodRepr, ClassRepr>> overridenInS = myFuture.findOverriddenMethods(m, s);
+
+ overridenInS.addAll(overridenMethods);
+
+ boolean allAbstract = true;
+ boolean visited = false;
+
+ for (final Pair<MethodRepr, ClassRepr> pp : overridenInS) {
+ final ClassRepr cc = pp.second;
+
+ if (cc == MOCK_CLASS) {
+ visited = true;
+ continue;
+ }
+
+ if (cc.name == it.name) {
+ continue;
+ }
+
+ visited = true;
+ allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
+
+ if (!allAbstract) {
+ break;
+ }
+ }
+
+ if (allAbstract && visited) {
+ final File source = myClassToSourceFile.get(p);
+
+ if (source != null) {
+ myAffectedFiles.add(source);
+ debug("Removed method is not abstract & overrides some abstract method which is not then over-overriden in subclass ", p);
+ debug("Affecting subclass source file ", source);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ });
+ }
+ }
+ debug("End of removed methods processing");
+ }
+
+ private void processChangedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ final Collection<Pair<MethodRepr, Difference>> changed = diff.methods().changed();
+ if (changed.isEmpty()) {
+ return;
+ }
+ debug("Processing changed methods:");
+ for (final Pair<MethodRepr, Difference> mr : changed) {
+ final MethodRepr m = mr.first;
+ final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
+ final boolean throwsChanged = !d.exceptions().unchanged();
+
+ debug("Method: ", m.name);
+
+ if (it.isAnnotation()) {
+ if (d.defaultRemoved()) {
+ debug("Class is annotation, default value is removed => adding annotation query");
+ final TIntHashSet l = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ l.add(m.name);
+ final UsageRepr.AnnotationUsage annotationUsage = (UsageRepr.AnnotationUsage)UsageRepr
+ .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), l, null);
+ state.myAnnotationQuery.add(annotationUsage);
+ }
+ }
+ else if (d.base() != Difference.NONE || throwsChanged) {
+ final TIntHashSet propagated = myFuture.propagateMethodAccess(m, it.name);
+
+ boolean affected = false;
+ boolean constrained = false;
+
+ final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();
+
+ if (d.packageLocalOn()) {
+ debug("Method became package-local, affecting method usages outside the package");
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
+
+ for (final UsageRepr.Usage usage : usages) {
+ state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
+ }
+
+ state.myAffectedUsages.addAll(usages);
+ affected = true;
+ constrained = true;
+ }
+
+ if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
+ if (!affected) {
+ debug("Return type, throws list or signature changed --- affecting method usages");
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
+
+ final List<Pair<MethodRepr, ClassRepr>> overridingMethods = new LinkedList<Pair<MethodRepr, ClassRepr>>();
+
+ myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);
+
+ for(final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
+ final ClassRepr aClass = p.getSecond();
+
+ if (aClass != MOCK_CLASS) {
+ final File fileName = myClassToSourceFile.get(aClass.name);
+ if (fileName != null) {
+ myAffectedFiles.add(fileName);
+ }
+ }
+ }
+
+ state.myAffectedUsages.addAll(usages);
+ }
+ }
+ else if ((d.base() & Difference.ACCESS) > 0) {
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
+ if (!affected) {
+ debug("Added static or private specifier or removed static specifier --- affecting method usages");
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
+ state.myAffectedUsages.addAll(usages);
+ }
+
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
+ debug("Added static specifier --- affecting subclasses");
+ myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false);
+ }
+ }
+ else {
+ if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Added final, public or abstract specifier --- affecting subclasses");
+ myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false);
+ }
+
+ if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
+ if (!constrained) {
+ debug("Added public or package-local method became protected --- affect method usages with protected constraint");
+ if (!affected) {
+ myFuture.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.myDependants);
+ state.myAffectedUsages.addAll(usages);
+ }
+
+ for (final UsageRepr.Usage usage : usages) {
+ state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ debug("End of changed methods processing");
+ }
+
+ private boolean processAddedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr classRepr) {
+ final Collection<FieldRepr> added = diff.fields().added();
+ if (added.isEmpty()) {
+ return true;
+ }
+ debug("Processing added fields");
+
+ for (final FieldRepr f : added) {
+ debug("Field: ", f.name);
+
+ final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
+ final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
+ final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
+ final boolean fPLocal = !fPrivate && !fProtected && !fPublic;
+
+ if (!fPrivate) {
+ final TIntHashSet subClasses = getAllSubclasses(classRepr.name);
+ subClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subClass) {
+ final ClassRepr r = myFuture.reprByName(subClass);
+ if (r != null) {
+ final File sourceFileName = myClassToSourceFile.get(subClass);
+ if (sourceFileName != null) {
+ if (r.isLocal()) {
+ debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
+ myAffectedFiles.add(sourceFileName);
+ }
+ else {
+ final int outerClass = r.getOuterClassName();
+ if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, f)) {
+ debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
+ myAffectedFiles.add(sourceFileName);
+ }
+ }
+ }
+ }
+
+ debug("Affecting field usages referenced from subclass ", subClass);
+ final TIntHashSet propagated = myFuture.propagateFieldAccess(f.name, subClass);
+ myFuture.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), state.myAffectedUsages, state.myDependants);
+
+ final TIntHashSet deps = myClassToClassDependency.get(subClass);
+
+ if (deps != null) {
+ addAll(state.myDependants, deps);
+ }
+ return true;
+ }
+ });
+ }
+
+ final Collection<Pair<FieldRepr, ClassRepr>> overriddenFields = new HashSet<Pair<FieldRepr, ClassRepr>>();
+ myFuture.addOverriddenFields(f, classRepr, overriddenFields);
+
+ for (final Pair<FieldRepr, ClassRepr> p : overriddenFields) {
+ final FieldRepr ff = p.first;
+ final ClassRepr cc = p.second;
+
+ final boolean ffPrivate = (ff.access & Opcodes.ACC_PRIVATE) > 0;
+ final boolean ffProtected = (ff.access & Opcodes.ACC_PROTECTED) > 0;
+ final boolean ffPublic = (ff.access & Opcodes.ACC_PUBLIC) > 0;
+ final boolean ffPLocal = Difference.isPackageLocal(ff.access);
+
+ if (!ffPrivate) {
+ final TIntHashSet propagated = myPresent.propagateFieldAccess(ff.name, cc.name);
+ final Set<UsageRepr.Usage> localUsages = new HashSet<UsageRepr.Usage>();
+
+ debug("Affecting usages of overridden field in class ", cc.name);
+ myFuture.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, state.myDependants);
+
+ if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
+
+ }
+ else {
+ Util.UsageConstraint constaint;
+
+ if ((ffProtected && fPublic) || (fProtected && ffPublic) || (ffPLocal && fProtected)) {
+ constaint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
+ }
+ else if (ffPublic && ffPLocal) {
+ constaint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
+ }
+ else {
+ constaint =
+ myFuture.new IntersectionConstraint(myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name)),
+ myFuture.new NegationConstraint(
+ myFuture.new PackageConstraint(cc.getPackageName())));
+ }
+
+ for (final UsageRepr.Usage usage : localUsages) {
+ state.myUsageConstraints.put(usage, constaint);
+ }
+ }
+
+ state.myAffectedUsages.addAll(localUsages);
+ }
+ }
+ }
+ debug("End of added fields processing");
+
+ return true;
+ }
+
+ private boolean processRemovedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ final Collection<FieldRepr> removed = diff.fields().removed();
+ if (removed.isEmpty()) {
+ return true;
+ }
+ debug("Processing removed fields:");
+
+ for (final FieldRepr f : removed) {
+ debug("Field: ", f.name);
+
+ if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
+ debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
+ if (myConstantSearch != null) {
+ myDelayedWorks.addConstantWork(it.name, f, true, false);
+ }
+ else {
+ if (!incrementalDecision(it.name, f, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+ }
+
+ final TIntHashSet propagated = myFuture.propagateFieldAccess(f.name, it.name);
+ myFuture.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ debug("End of removed fields processing");
+
+ return true;
+ }
+
+ private boolean processChangedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ final Collection<Pair<FieldRepr, Difference>> changed = diff.fields().changed();
+ if (changed.isEmpty()) {
+ return true;
+ }
+ debug("Processing changed fields:");
+
+ for (final Pair<FieldRepr, Difference> f : changed) {
+ final Difference d = f.second;
+ final FieldRepr field = f.first;
+
+ debug("Field: ", field.name);
+
+ if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & DESPERATE_MASK) == DESPERATE_MASK) {
+ final int changedModifiers = d.addedModifiers() | d.removedModifiers();
+ final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0;
+ final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0;
+ final boolean valueChanged = (d.base() & Difference.VALUE) > 0 && d.hadValue();
+
+ if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) {
+ debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
+ if (myConstantSearch != null) {
+ myDelayedWorks.addConstantWork(it.name, field, false, accessChanged);
+ }
+ else {
+ if (!incrementalDecision(it.name, field, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+ }
+ }
+
+ if (d.base() != Difference.NONE) {
+ final TIntHashSet propagated = myFuture.propagateFieldAccess(field.name, it.name);
+
+ if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
+ debug("Type or signature changed --- affecting field usages");
+ myFuture
+ .affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ else if ((d.base() & Difference.ACCESS) > 0) {
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
+ debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
+ myFuture
+ .affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants);
+ }
+ else {
+ boolean affected = false;
+ final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();
+
+ if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
+ debug("Added final modifier --- affecting field assign usages");
+ myFuture.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, state.myDependants);
+ state.myAffectedUsages.addAll(usages);
+ affected = true;
+ }
+
+ if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
+ debug("Removed public modifier, affecting field usages with appropriate constraint");
+ if (!affected) {
+ myFuture.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, state.myDependants);
+ state.myAffectedUsages.addAll(usages);
+ }
+
+ for (final UsageRepr.Usage usage : usages) {
+ if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0) {
+ state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(it.name));
+ }
+ else {
+ state.myUsageConstraints.put(usage, myFuture.new PackageConstraint(it.getPackageName()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ debug("End of changed fields processing");
+
+ return true;
+ }
+
+ private boolean processChangedClasses(final DiffState state) {
+ final Collection<Pair<ClassRepr, Difference>> changedClasses = state.myClassDiff.changed();
+ if (!changedClasses.isEmpty()) {
+ debug("Processing changed classes:");
+
+ for (final Pair<ClassRepr, Difference> changed : changedClasses) {
+ final ClassRepr changedClass = changed.first;
+ final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
+
+ myDelta.addChangedClass(changedClass.name);
+
+ debug("Changed: ", changedClass.name);
+
+ final int addedModifiers = diff.addedModifiers();
+
+ final boolean superClassChanged = (diff.base() & Difference.SUPERCLASS) > 0;
+ final boolean interfacesChanged = !diff.interfaces().unchanged();
+ final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;
+
+ if (superClassChanged) {
+ myDelta.registerRemovedSuperClass(changedClass.name, changedClass.getSuperClass().className);
+
+ final ClassRepr newClass = myDelta.getReprByName(null, changedClass.name);
+
+ assert (newClass != null);
+
+ myDelta.registerAddedSuperClass(changedClass.name, newClass.getSuperClass().className);
+ }
+
+ if (interfacesChanged) {
+ for (final TypeRepr.AbstractType typ : diff.interfaces().removed()) {
+ myDelta.registerRemovedSuperClass(changedClass.name, ((TypeRepr.ClassType)typ).className);
+ }
+
+ for (final TypeRepr.AbstractType typ : diff.interfaces().added()) {
+ myDelta.registerAddedSuperClass(changedClass.name, ((TypeRepr.ClassType)typ).className);
+ }
+ }
+
+ if (myEasyMode) {
+ continue;
+ }
+
+ myPresent.appendDependents(changedClass, state.myDependants);
+
+ if (superClassChanged || interfacesChanged || signatureChanged) {
+ debug("Superclass changed: ", superClassChanged);
+ debug("Interfaces changed: ", interfacesChanged);
+ debug("Signature changed ", signatureChanged);
+
+ final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
+ final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();
+
+ debug("Extends changed: ", extendsChanged);
+ debug("Interfaces removed: ", interfacesRemoved);
+
+ myFuture.affectSubclasses(changedClass.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, extendsChanged || interfacesRemoved || signatureChanged);
+
+ if (!changedClass.isAnonymous()) {
+ final TIntHashSet parents = new TIntHashSet();
+ myPresent.collectSupersRecursively(changedClass.name, parents);
+ final TIntHashSet futureParents = new TIntHashSet();
+ myFuture.collectSupersRecursively(changedClass.name, futureParents);
+ parents.removeAll(futureParents.toArray());
+ parents.remove(myObjectClassName);
+ if (!parents.isEmpty()) {
+ parents.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int className) {
+ debug("Affecting usages in generic type parameter bounds of class: ", className);
+ state.myAffectedUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));
+
+ final TIntHashSet depClasses = myClassToClassDependency.get(className);
+ if (depClasses != null) {
+ addAll(state.myDependants, depClasses);
+ }
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+ if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
+ debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
+ state.myAffectedUsages.add(changedClass.createUsage());
+ }
+
+ if (changedClass.isAnnotation() && changedClass.getRetentionPolicy() == RetentionPolicy.SOURCE) {
+ debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
+ if (!incrementalDecision(changedClass.getOuterClassName(), changedClass, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+
+ if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
+ debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
+ final UsageRepr.Usage usage = changedClass.createUsage();
+
+ state.myAffectedUsages.add(usage);
+ state.myUsageConstraints.put(usage, myFuture.new InheritanceConstraint(changedClass.name));
+ }
+
+ if (diff.packageLocalOn()) {
+ debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
+ final UsageRepr.Usage usage = changedClass.createUsage();
+
+ state.myAffectedUsages.add(usage);
+ state.myUsageConstraints.put(usage, myFuture.new PackageConstraint(changedClass.getPackageName()));
+ }
+
+ if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
+ debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
+ state.myAffectedUsages.add(changedClass.createUsage());
+ }
+
+ if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
+ debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
+ state.myAffectedUsages.add(UsageRepr.createClassNewUsage(myContext, changedClass.name));
+ }
+
+ if (changedClass.isAnnotation()) {
+ debug("Class is annotation, performing annotation-specific analysis");
+
+ if (diff.retentionChanged()) {
+ debug("Retention policy change detected, adding class usage to affected usages");
+ state.myAffectedUsages.add(changedClass.createUsage());
+ }
+ else {
+ final Collection<ElemType> removedtargets = diff.targets().removed();
+
+ if (removedtargets.contains(ElemType.LOCAL_VARIABLE)) {
+ debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
+ if (!incrementalDecision(changedClass.getOuterClassName(), changedClass, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+
+ if (!removedtargets.isEmpty()) {
+ debug("Removed some annotation targets, adding annotation query");
+ final UsageRepr.AnnotationUsage annotationUsage = (UsageRepr.AnnotationUsage)UsageRepr
+ .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, changedClass.name), null, EnumSet.copyOf(removedtargets));
+ state.myAnnotationQuery.add(annotationUsage);
+ }
+
+ for (final MethodRepr m : diff.methods().added()) {
+ if (!m.hasValue()) {
+ debug("Added method with no default value: ", m.name);
+ debug("Adding class usage to affected usages");
+ state.myAffectedUsages.add(changedClass.createUsage());
+ }
+ }
+ }
+
+ debug("End of annotation-specific analysis");
+ }
+
+ processAddedMethods(state, diff, changedClass);
+ processRemovedMethods(state, diff, changedClass);
+ processChangedMethods(state, diff, changedClass);
+
+ if (!processAddedFields(state, diff, changedClass)) {
+ return false;
+ }
+
+ if (!processRemovedFields(state, diff, changedClass)) {
+ return false;
+ }
+
+ if (!processChangedFields(state, diff, changedClass)) {
+ return false;
+ }
+ }
+ debug("End of changed classes processing");
+ }
+
+ return !myEasyMode;
+ }
+
+ private void processRemovedClases(final DiffState state) {
+ final Collection<ClassRepr> removed = state.myClassDiff.removed();
+ if (removed.isEmpty()) {
+ return;
+ }
+ debug("Processing removed classes:");
+ for (final ClassRepr c : removed) {
+ myDelta.addDeletedClass(c);
+
+ final File fileName = myClassToSourceFile.get(c.name);
+
+ if (fileName != null) {
+ myDelta.myChangedFiles.add(fileName);
+ }
+
+ if (!myEasyMode) {
+ myPresent.appendDependents(c, state.myDependants);
+ debug("Adding usages of class ", c.name);
+ state.myAffectedUsages.add(c.createUsage());
+ }
+ }
+ debug("End of removed classes processing.");
+ }
+
+ private void processAddedClasses(final DiffState state) {
+ final Collection<ClassRepr> addedClasses = state.myClassDiff.added();
+ if (addedClasses.isEmpty()) {
+ return;
+ }
+
+ debug("Processing added classes:");
+ for (final ClassRepr c : addedClasses) {
+ debug("Class name: ", c.name);
+ myDelta.addChangedClass(c.name);
+
+ for (final int sup : c.getSupers()) {
+ myDelta.registerAddedSuperClass(c.name, sup);
+ }
+
+ if (!myEasyMode) {
+ final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
+
+ if (depClasses != null) {
+ depClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int depClass) {
+ final File fName = myClassToSourceFile.get(depClass);
+ if (fName != null) {
+ if (myFilter == null || myFilter.accept(fName)) {
+ debug("Adding dependent file ", fName);
+ myAffectedFiles.add(fName);
+ }
+ }
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+ debug("End of added classes processing.");
+ }
+
+ private void calculateAffectedFiles(final DiffState state) {
+ debug("Checking dependent classes:");
+
+ state.myDependants.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int depClass) {
+ final File depFile = myClassToSourceFile.get(depClass);
+
+ if (depFile == null || myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
+ return true;
+ }
+
+ debug("Dependent class: ", depClass);
+
+ final ClassRepr classRepr = getReprByName(depFile, depClass);
+
+ if (classRepr == null) {
+ return true;
+ }
+
+ final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
+
+ if (depUsages == null || depUsages.isEmpty()) {
+ return true;
+ }
+
+ for (UsageRepr.Usage usage : depUsages) {
+ if (usage instanceof UsageRepr.AnnotationUsage) {
+ for (final UsageRepr.AnnotationUsage query : state.myAnnotationQuery) {
+ if (query.satisfies(usage)) {
+ debug("Added file due to annotation query");
+ myAffectedFiles.add(depFile);
+
+ return true;
+ }
+ }
+ }
+ else if (state.myAffectedUsages.contains(usage)) {
+ final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
+
+ if (constraint == null) {
+ debug("Added file with no constraints");
+ myAffectedFiles.add(depFile);
+
+ return true;
+ }
+ else {
+ if (constraint.checkResidence(depClass)) {
+ debug("Added file with satisfied constraint");
+ myAffectedFiles.add(depFile);
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ });
+ }
+
+ boolean differentiate() {
+ synchronized (myLock) {
+ myDelta.myIsDifferentiated = true;
+
+ if (myDelta.myIsRebuild) {
+ return true;
+ }
+
+ debug("Begin of Differentiate:");
+ debug("Easy mode: ", myEasyMode);
+
+ processDisappearedClasses();
+
+ final List<FileClasses> newClasses = new ArrayList<FileClasses>();
+ myDelta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
+ @Override
+ public boolean execute(File fileName, Collection<ClassRepr> classes) {
+ newClasses.add(new FileClasses(fileName, classes));
+ return true;
+ }
+ });
+
+ for (final FileClasses compiledFile : newClasses) {
+ final File fileName = compiledFile.myFileName;
+ final Set<ClassRepr> classes = compiledFile.myFileClasses;
+ final Set<ClassRepr> pastClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
+ final DiffState state = new DiffState(Difference.make(pastClasses, classes));
+
+ if (!processChangedClasses(state)) {
+ if (!myEasyMode) {
+ // turning non-incremental
+ return false;
+ }
+ }
+
+ processRemovedClases(state);
+ processAddedClasses(state);
+
+ if (!myEasyMode) {
+ calculateAffectedFiles(state);
+ }
+ }
+
+ debug("End of Differentiate.");
+
+ if (myEasyMode) {
+ return false;
+ }
+
+ final Collection<String> removed = myDelta.myRemovedFiles;
+ if (removed != null) {
+ for (final String r : removed) {
+ myAffectedFiles.remove(new File(r));
+ }
+ }
+ return myDelayedWorks.doWork(myAffectedFiles);
+ }
+ }
+ }
+
+ public void differentiateOnRebuild(final Mappings delta) {
+ new Differential(delta).differentiate();
+ }
+
+ public void differentiateOnNonIncrementalMake(final Mappings delta,
+ final Collection<String> removed,
+ final Collection<File> filesToCompile) {
+ new Differential(delta, removed, filesToCompile).differentiate();
+ }
+
+ public boolean differentiateOnIncrementalMake
+ (final Mappings delta,
+ final Collection<String> removed,
+ final Collection<File> filesToCompile,
+ final Collection<File> compiledFiles,
+ final Collection<File> affectedFiles,
+ final DependentFilesFilter filter,
+ @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
+ return new Differential(delta, removed, filesToCompile, compiledFiles, affectedFiles, filter, constantSearch).differentiate();
+ }
+
+ private void cleanupBackDependency(final int className,
+ @Nullable Set<UsageRepr.Usage> usages,
+ final IntIntMultiMaplet buffer) {
+ if (usages == null) {
+ final ClassRepr repr = getReprByName(null, className);
+
+ if (repr != null) {
+ usages = repr.getUsages();
+ }
+ }
+
+ if (usages != null) {
+ for (final UsageRepr.Usage u : usages) {
+ buffer.put(u.getOwner(), className);
+ }
+ }
+ }
+
+ private void cleanupRemovedClass(final Mappings delta,
+ @NotNull final ClassRepr cr,
+ final Set<UsageRepr.Usage> usages,
+ final IntIntMultiMaplet dependenciesTrashBin) {
+ final int className = cr.name;
+
+ for (final int superSomething : cr.getSupers()) {
+ delta.registerRemovedSuperClass(className, superSomething);
+ }
+
+ cleanupBackDependency(className, usages, dependenciesTrashBin);
+
+ myClassToClassDependency.remove(className);
+ myClassToSubclasses.remove(className);
+ myClassToSourceFile.remove(className);
+ }
+
+ public void integrate(final Mappings delta) {
+ synchronized (myLock) {
+ try {
+ assert (delta.isDifferentiated());
+
+ final Collection<String> removed = delta.myRemovedFiles;
+
+ delta.runPostPasses();
+
+ final IntIntMultiMaplet dependenciesTrashBin = new IntIntTransientMultiMaplet();
+
+ if (removed != null) {
+ for (final String file : removed) {
+ final File fileName = new File(file);
+ final Set<ClassRepr> fileClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
+
+ if (fileClasses != null) {
+ for (final ClassRepr aClass : fileClasses) {
+ cleanupRemovedClass(delta, aClass, aClass.getUsages(), dependenciesTrashBin);
+ }
+ mySourceFileToClasses.remove(fileName);
+ }
+ }
+ }
+
+ if (!delta.isRebuild()) {
+ for (final ClassRepr repr : delta.getDeletedClasses()) {
+ cleanupRemovedClass(delta, repr, repr.getUsages(), dependenciesTrashBin);
+ }
+
+ final TIntHashSet superClasses = new TIntHashSet();
+ final IntIntTransientMultiMaplet addedSuperClasses = delta.getAddedSuperClasses();
+ final IntIntTransientMultiMaplet removedSuperClasses = delta.getRemovedSuperClasses();
+
+ addAllKeys(superClasses, addedSuperClasses);
+ addAllKeys(superClasses, removedSuperClasses);
+
+ superClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int superClass) {
+ final TIntHashSet added = addedSuperClasses.get(superClass);
+ final TIntHashSet removed = removedSuperClasses.get(superClass);
+
+ final TIntHashSet old = myClassToSubclasses.get(superClass);
+
+ if (old == null) {
+ myClassToSubclasses.replace(superClass, added);
+ }
+ else {
+ if (removed != null) {
+ old.removeAll(removed.toArray());
+ }
+
+ if (added != null) {
+ old.addAll(added.toArray());
+ }
+
+ myClassToSubclasses.replace(superClass, old);
+ }
+
+ return true;
+ }
+ });
+
+ delta.getChangedClasses().forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int className) {
+ final File sourceFile = delta.myClassToSourceFile.get(className);
+ if (sourceFile != null) {
+ myClassToSourceFile.put(className, sourceFile);
+ }
+ else {
+ myClassToSourceFile.remove(className);
+ }
+
+ cleanupBackDependency(className, null, dependenciesTrashBin);
+
+ return true;
+ }
+ });
+
+ delta.getChangedFiles().forEach(new TObjectProcedure<File>() {
+ @Override
+ public boolean execute(final File fileName) {
+ final Collection<ClassRepr> classes = delta.mySourceFileToClasses.get(fileName);
+ mySourceFileToClasses.replace(fileName, classes);
+ return true;
+ }
+ });
+ }
+ else {
+ myClassToSubclasses.putAll(delta.myClassToSubclasses);
+ myClassToSourceFile.putAll(delta.myClassToSourceFile);
+ mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
+ }
+
+ // updating classToClass dependencies
+
+ final TIntHashSet affectedClasses = new TIntHashSet();
+
+ addAllKeys(affectedClasses, dependenciesTrashBin);
+ addAllKeys(affectedClasses, delta.myClassToClassDependency);
+
+ affectedClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int aClass) {
+ final TIntHashSet now = delta.myClassToClassDependency.get(aClass);
+ final TIntHashSet toRemove = dependenciesTrashBin.get(aClass);
+ final boolean hasDataToAdd = now != null && !now.isEmpty();
+
+ if (toRemove != null && !toRemove.isEmpty()) {
+ final TIntHashSet current = myClassToClassDependency.get(aClass);
+ if (current != null && !current.isEmpty()) {
+ final TIntHashSet before = new TIntHashSet();
+ addAll(before, current);
+
+ final boolean removed = current.removeAll(toRemove.toArray());
+ final boolean added = hasDataToAdd && current.addAll(now.toArray());
+
+ if ((removed && !added) || (!removed && added) || !before.equals(current)) {
+ myClassToClassDependency.replace(aClass, current);
+ }
+ }
+ else {
+ if (hasDataToAdd) {
+ myClassToClassDependency.put(aClass, now);
+ }
+ }
+ }
+ else {
+ // nothing to remove for this class
+ if (hasDataToAdd) {
+ myClassToClassDependency.put(aClass, now);
+ }
+ }
+ return true;
+ }
+ });
+ }
+ finally {
+ delta.close();
+ }
+ }
+ }
+
+ public Callbacks.Backend getCallback() {
+ return new Callbacks.Backend() {
+ public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
+ synchronized (myLock) {
+ final int classFileNameS = myContext.get(classFileName);
+ final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
+ final ClassRepr repr = result.first;
+ if (repr != null) {
+ final Set<UsageRepr.Usage> localUsages = result.second;
+ final File sourceFile = new File(sourceFileName);
+ final int className = repr.name;
+
+ myClassToSourceFile.put(className, sourceFile);
+ mySourceFileToClasses.put(sourceFile, repr);
+
+ for (final int s : repr.getSupers()) {
+ myClassToSubclasses.put(s, className);
+ }
+
+ for (final UsageRepr.Usage u : localUsages) {
+ final int owner = u.getOwner();
+
+ if (owner != className) {
+ myClassToClassDependency.put(owner, className);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void registerImports(final String className, final Collection<String> imports, Collection<String> staticImports) {
+ final List<String> allImports = new ArrayList<String>();
+ for (String anImport : imports) {
+ if (!anImport.endsWith("*")) {
+ allImports.add(anImport); // filter out wildcard imports
+ }
+ }
+ for (final String s : staticImports) {
+ int i = s.length() - 1;
+ for (; s.charAt(i) != '.'; i--) ;
+ final String anImport = s.substring(0, i);
+ if (!anImport.endsWith("*")) {
+ allImports.add(anImport); // filter out wildcard imports
+ }
+ }
+
+ if (!allImports.isEmpty()) {
+ myPostPasses.offer(new Runnable() {
+ public void run() {
+ final int rootClassName = myContext.get(className.replace(".", "/"));
+ final File fileName = myClassToSourceFile.get(rootClassName);
+ final ClassRepr repr = fileName != null? getReprByName(fileName, rootClassName) : null;
+
+ for (final String i : allImports) {
+ final int iname = myContext.get(i.replace(".", "/"));
+ myClassToClassDependency.put(iname, rootClassName);
+ if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
+ mySourceFileToClasses.put(fileName, repr);
+ }
+ }
+ }
+ });
+ }
+ }
+ };
+ }
+
+ @Nullable
+ public Set<ClassRepr> getClasses(final String sourceFileName) {
+ synchronized (myLock) {
+ return (Set<ClassRepr>)mySourceFileToClasses.get(new File(sourceFileName));
+ }
+ }
+
+ public void close() {
+ synchronized (myLock) {
+ myClassToSubclasses.close();
+ myClassToClassDependency.close();
+ mySourceFileToClasses.close();
+ myClassToSourceFile.close();
+
+ if (!myIsDelta) {
+ // only close if you own the context
+ final DependencyContext context = myContext;
+ if (context != null) {
+ context.close();
+ myContext = null;
+ }
+ }
+ else {
+ if (!myDeltaIsTransient) {
+ FileUtil.delete(myRootDir);
+ }
+ }
+ }
+ }
+
+ public void flush(final boolean memoryCachesOnly) {
+ synchronized (myLock) {
+ myClassToSubclasses.flush(memoryCachesOnly);
+ myClassToClassDependency.flush(memoryCachesOnly);
+ mySourceFileToClasses.flush(memoryCachesOnly);
+ myClassToSourceFile.flush(memoryCachesOnly);
+
+ if (!myIsDelta) {
+ // flush if you own the context
+ final DependencyContext context = myContext;
+ if (context != null) {
+ context.clearMemoryCaches();
+ if (!memoryCachesOnly) {
+ context.flush();
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean addAll(final TIntHashSet whereToAdd, TIntHashSet whatToAdd) {
+ if (whatToAdd.isEmpty()) {
+ return false;
+ }
+ final Ref<Boolean> changed = new Ref<Boolean>(Boolean.FALSE);
+ whatToAdd.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ if (whereToAdd.add(value)) {
+ changed.set(Boolean.TRUE);
+ }
+ return true;
+ }
+ });
+ return changed.get();
+ }
+
+ private static void addAllKeys(final TIntHashSet whereToAdd, final IntIntMultiMaplet maplet) {
+ maplet.forEachEntry(new TIntObjectProcedure<TIntHashSet>() {
+ @Override
+ public boolean execute(int key, TIntHashSet b) {
+ whereToAdd.add(key);
+ return true;
+ }
+ });
+ }
+
+ private void registerAddedSuperClass(final int aClass, final int superClass) {
+ assert (myAddedSuperClasses != null);
+ myAddedSuperClasses.put(superClass, aClass);
+ }
+
+ private void registerRemovedSuperClass(final int aClass, final int superClass) {
+ assert (myRemovedSuperClasses != null);
+ myRemovedSuperClasses.put(superClass, aClass);
+ }
+
+ private boolean isDifferentiated() {
+ return myIsDifferentiated;
+ }
+
+ private boolean isRebuild() {
+ return myIsRebuild;
+ }
+
+ private void addDeletedClass(final ClassRepr cr) {
+ assert (myDeletedClasses != null);
+
+ myDeletedClasses.add(cr);
+
+ addChangedClass(cr.name);
+ }
+
+ private void addChangedClass(final int it) {
+ assert (myChangedClasses != null && myChangedFiles != null);
+ myChangedClasses.add(it);
+
+ final File file = myClassToSourceFile.get(it);
+
+ if (file != null) {
+ myChangedFiles.add(file);
+ }
+ }
+
+ @NotNull
+ private Set<ClassRepr> getDeletedClasses() {
+ return myDeletedClasses == null ? Collections.<ClassRepr>emptySet() : Collections.unmodifiableSet(myDeletedClasses);
+ }
+
+ private TIntHashSet getChangedClasses() {
+ return myChangedClasses;
+ }
+
+ private THashSet<File> getChangedFiles() {
+ return myChangedFiles;
+ }
+
+ private static void debug(final String s) {
+ LOG.debug(s);
+ }
+
+ private void debug(final String comment, final int s) {
+ myDebugS.debug(comment, s);
+ }
+
+ private void debug(final String comment, final File f) {
+ debug(comment, f.getPath());
+ }
+
+ private void debug(final String comment, final String s) {
+ myDebugS.debug(comment, s);
+ }
+
+ private void debug(final String comment, final boolean s) {
+ myDebugS.debug(comment, s);
+ }
+
+ public void toStream(final PrintStream stream) {
+ final Streamable[] data = {
+ myClassToSubclasses,
+ myClassToClassDependency,
+ mySourceFileToClasses,
+ myClassToSourceFile,
+ };
+
+ final String[] info = {
+ "ClassToSubclasses",
+ "ClassToClassDependency",
+ "SourceFileToClasses",
+ "ClassToSourceFile",
+ "SourceFileToAnnotationUsages",
+ "SourceFileToUsages"
+ };
+
+ for (int i = 0; i < data.length; i++) {
+ stream.print("Begin Of ");
+ stream.println(info[i]);
+
+ data[i].toStream(myContext, stream);
+
+ stream.print("End Of ");
+ stream.println(info[i]);
+ }
+ }
+
+ public void toStream(File outputRoot) {
+ final Streamable[] data = {
+ myClassToSubclasses,
+ myClassToClassDependency,
+ mySourceFileToClasses,
+ myClassToSourceFile,
+ };
+
+ final String[] info = {
+ "ClassToSubclasses",
+ "ClassToClassDependency",
+ "SourceFileToClasses",
+ "ClassToSourceFile",
+ };
+
+ for (int i = 0; i < data.length; i++) {
+ final File file = new File(outputRoot, info[i]);
+ FileUtil.createIfDoesntExist(file);
+ try {
+ final PrintStream stream = new PrintStream(file);
+ try {
+ data[i].toStream(myContext, stream);
+ }
+ finally {
+ stream.close();
+ }
+ }
+ catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
new file mode 100644
index 000000000000..62d811847c12
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.asm4.Type;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author: db
+ * Date: 01.02.11
+ */
+class MethodRepr extends ProtoMember {
+ interface Predicate {
+ boolean satisfy(MethodRepr m);
+ }
+
+ public final TypeRepr.AbstractType[] myArgumentTypes;
+ public final Set<TypeRepr.AbstractType> myExceptions;
+
+ public abstract class Diff extends Difference {
+ public abstract Specifier<TypeRepr.AbstractType> exceptions();
+
+ public abstract boolean defaultAdded();
+
+ public abstract boolean defaultRemoved();
+ }
+
+ @Override
+ public Difference difference(final Proto past) {
+ final Difference diff = super.difference(past);
+ final Difference.Specifier<TypeRepr.AbstractType> excs = Difference.make(((MethodRepr)past).myExceptions, myExceptions);
+
+ return new Diff() {
+ @Override
+ public int addedModifiers() {
+ return diff.addedModifiers();
+ }
+
+ @Override
+ public int removedModifiers() {
+ return diff.removedModifiers();
+ }
+
+ @Override
+ public boolean no() {
+ return base() == NONE && !defaultAdded() && !defaultRemoved() && excs.unchanged();
+ }
+
+ @Override
+ public boolean defaultAdded() {
+ return hasValue() && !((MethodRepr)past).hasValue();
+ }
+
+ @Override
+ public boolean defaultRemoved() {
+ return !hasValue() && ((MethodRepr)past).hasValue();
+ }
+
+ @Override
+ public Specifier<TypeRepr.AbstractType> exceptions() {
+ return excs;
+ }
+
+ @Override
+ public int base() {
+ return diff.base();
+ }
+
+ @Override
+ public boolean packageLocalOn() {
+ return diff.packageLocalOn();
+ }
+
+ @Override
+ public boolean hadValue() {
+ return ((MethodRepr)past).hasValue();
+ }
+
+ @Override
+ public boolean weakedAccess() {
+ return diff.weakedAccess();
+ }
+ };
+ }
+
+ public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
+ myType.updateClassUsages(context, owner, s);
+
+ for (int i = 0; i < myArgumentTypes.length; i++) {
+ myArgumentTypes[i].updateClassUsages(context, owner, s);
+ }
+
+ if (myExceptions != null) {
+ for (TypeRepr.AbstractType typ : myExceptions) {
+ typ.updateClassUsages(context, owner, s);
+ }
+ }
+ }
+
+ public MethodRepr(final DependencyContext context,
+ final int a,
+ final int n,
+ final int s,
+ final String d,
+ final String[] e,
+ final Object value) {
+ super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value);
+ myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, new HashSet<TypeRepr.AbstractType>());
+ myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d));
+ }
+
+ public MethodRepr(final DependencyContext context, final DataInput in) {
+ super(context, in);
+ try {
+ final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
+ final int size = in.readInt();
+ myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[size]);
+ myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new HashSet<TypeRepr.AbstractType>(), in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ super.save(out);
+ RW.save(myArgumentTypes, out);
+ RW.save(myExceptions, out);
+ }
+
+ public static DataExternalizer<MethodRepr> externalizer(final DependencyContext context) {
+ return new DataExternalizer<MethodRepr>() {
+ @Override
+ public void save(final DataOutput out, final MethodRepr value) throws IOException {
+ value.save(out);
+ }
+
+ @Override
+ public MethodRepr read(DataInput in) throws IOException {
+ return new MethodRepr(context, in);
+ }
+ };
+ }
+
+ static Predicate equalByJavaRules(final MethodRepr me) {
+ return new Predicate() {
+ @Override
+ public boolean satisfy(MethodRepr that) {
+ if (me == that) return true;
+ return me.name == that.name && Arrays.equals(me.myArgumentTypes, that.myArgumentTypes);
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodRepr that = (MethodRepr)o;
+
+ return name == that.name && myType.equals(that.myType) && Arrays.equals(myArgumentTypes, that.myArgumentTypes);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * (31 * Arrays.hashCode(myArgumentTypes) + myType.hashCode()) + name;
+ }
+
+ private String getDescr(final DependencyContext context) {
+ final StringBuilder buf = new StringBuilder();
+
+ buf.append("(");
+
+ for (TypeRepr.AbstractType t : myArgumentTypes) {
+ buf.append(t.getDescr(context));
+ }
+
+ buf.append(")");
+ buf.append(myType.getDescr(context));
+
+ return buf.toString();
+ }
+
+ public UsageRepr.Usage createUsage(final DependencyContext context, final int owner) {
+ return UsageRepr.createMethodUsage(context, name, owner, getDescr(context));
+ }
+
+ public UsageRepr.Usage createMetaUsage(final DependencyContext context, final int owner) {
+ return UsageRepr.createMetaMethodUsage(context, name, owner, getDescr(context));
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ super.toStream(context, stream);
+ stream.print(" Arguments : ");
+ for (TypeRepr.AbstractType t : myArgumentTypes) {
+ stream.print(t.getDescr(context));
+ stream.print("; ");
+ }
+ stream.println();
+
+ final TypeRepr.AbstractType[] es = myExceptions.toArray(new TypeRepr.AbstractType[myExceptions.size()]);
+ Arrays.sort(es, new Comparator<TypeRepr.AbstractType>() {
+ @Override
+ public int compare(final TypeRepr.AbstractType o1, final TypeRepr.AbstractType o2) {
+ return o1.getDescr(context).compareTo(o2.getDescr(context));
+ }
+ });
+ stream.print(" Exceptions : ");
+ for (final TypeRepr.AbstractType e : es) {
+ stream.print(e.getDescr(context));
+ stream.print("; ");
+ }
+ stream.println();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java
new file mode 100644
index 000000000000..35edf8421a93
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
+import gnu.trove.TObjectObjectProcedure;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * @author: db
+ * Date: 03.11.11
+ */
+abstract class ObjectObjectMultiMaplet<K, V extends Streamable> implements Streamable {
+ abstract boolean containsKey(final K key);
+
+ abstract Collection<V> get(final K key);
+
+ abstract void put(final K key, final V value);
+
+ abstract void put(final K key, final Collection<V> value);
+
+ abstract void replace(final K key, final Collection<V> value);
+
+ abstract void putAll(ObjectObjectMultiMaplet<K, V> m);
+
+ abstract void replaceAll(ObjectObjectMultiMaplet<K, V> m);
+
+ abstract void remove(final K key);
+
+ abstract void removeFrom(final K key, final V value);
+
+ abstract void removeAll(final K key, final Collection<V> value);
+
+ abstract void close();
+
+ abstract void forEachEntry(TObjectObjectProcedure<K, Collection<V>> procedure);
+
+ abstract void flush(boolean memoryCachesOnly);
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+
+ final List<Pair<K, String>> keys = new ArrayList<Pair<K, String>>();
+ forEachEntry(new TObjectObjectProcedure<K, Collection<V>>() {
+ @Override
+ public boolean execute(final K a, final Collection<V> b) {
+ // on case-insensitive file systems save paths in normalized (lowercase) format in order to make tests run deterministically
+ final String keyStr = a instanceof File && !SystemInfo.isFileSystemCaseSensitive?
+ ((File)a).getPath().toLowerCase(Locale.US) :
+ a.toString();
+ keys.add(new Pair<K, String>(a, keyStr));
+ return true;
+ }
+ });
+
+ Collections.sort(keys, new Comparator<Pair<K, String>>() {
+ @Override
+ public int compare(Pair<K, String> o1, Pair<K, String> o2) {
+ return o1.second.compareTo(o2.second);
+ }
+ });
+
+ for (final Pair<K, String> a: keys) {
+ final Collection<V> b = get(a.first);
+
+ stream.print(" Key: ");
+ stream.println(a.second);
+ stream.println(" Values:");
+
+ final List<String> list = new LinkedList<String>();
+
+ for (final V value : b) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream s = new PrintStream(baos);
+
+ value.toStream(context, s);
+
+ list.add(baos.toString());
+ }
+
+ Collections.sort(list);
+
+ for (final String l : list) {
+ stream.print(l);
+ }
+
+ stream.println(" End Of Values");
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java
new file mode 100644
index 000000000000..ed6bc9092082
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.TObjectObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.*;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/10/12
+ */
+public class ObjectObjectPersistentMultiMaplet<K, V extends Streamable> extends ObjectObjectMultiMaplet<K, V>{
+ private static final Collection NULL_COLLECTION = Collections.emptySet();
+ private static final int CACHE_SIZE = 128;
+ private final PersistentHashMap<K, Collection<V>> myMap;
+ private final DataExternalizer<V> myValueExternalizer;
+ private final SLRUCache<K, Collection> myCache;
+
+ public ObjectObjectPersistentMultiMaplet(final File file,
+ final KeyDescriptor<K> keyExternalizer,
+ final DataExternalizer<V> valueExternalizer,
+ final CollectionFactory<V> collectionFactory) throws IOException {
+ myValueExternalizer = valueExternalizer;
+ myMap = new PersistentHashMap<K, Collection<V>>(file, keyExternalizer, new CollectionDataExternalizer<V>(valueExternalizer, collectionFactory));
+ myCache = new SLRUCache<K, Collection>(CACHE_SIZE, CACHE_SIZE) {
+ @NotNull
+ @Override
+ public Collection createValue(K key) {
+ try {
+ final Collection<V> collection = myMap.get(key);
+ return collection == null? NULL_COLLECTION : collection;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+
+ @Override
+ public boolean containsKey(final K key) {
+ try {
+ return myMap.containsMapping(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Collection<V> get(final K key) {
+ final Collection<V> collection = myCache.get(key);
+ return collection == NULL_COLLECTION? null : collection;
+ }
+
+ @Override
+ public void replace(K key, Collection<V> value) {
+ try {
+ myCache.remove(key);
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final K key, final Collection<V> value) {
+ try {
+ myCache.remove(key);
+ myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
+ public void append(DataOutput out) throws IOException {
+ for (V v : value) {
+ myValueExternalizer.save(out, v);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void put(final K key, final V value) {
+ put(key, Collections.singleton(value));
+ }
+
+ @Override
+ public void removeAll(K key, Collection<V> values) {
+ try {
+ final Collection collection = myCache.get(key);
+
+ if (collection != NULL_COLLECTION) {
+ if (collection.removeAll(values)) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, (Collection<V>)collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void removeFrom(final K key, final V value) {
+ try {
+ final Collection collection = myCache.get(key);
+
+ if (collection != NULL_COLLECTION) {
+ if (collection.remove(value)) {
+ myCache.remove(key);
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, (Collection<V>)collection);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void remove(final K key) {
+ try {
+ myCache.remove(key);
+ myMap.remove(key);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void putAll(ObjectObjectMultiMaplet<K, V> m) {
+ m.forEachEntry(new TObjectObjectProcedure<K, Collection<V>>() {
+ @Override
+ public boolean execute(K key, Collection<V> value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void replaceAll(ObjectObjectMultiMaplet<K, V> m) {
+ m.forEachEntry(new TObjectObjectProcedure<K, Collection<V>>() {
+ @Override
+ public boolean execute(K key, Collection<V> value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ try {
+ myCache.clear();
+ myMap.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ else {
+ myMap.force();
+ }
+ }
+
+ @Override
+ public void forEachEntry(final TObjectObjectProcedure<K, Collection<V>> procedure) {
+ try {
+ myMap.processKeysWithExistingMapping(new Processor<K>() {
+ @Override
+ public boolean process(K key) {
+ try {
+ return procedure.execute(key, myMap.get(key));
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static class CollectionDataExternalizer<V> implements DataExternalizer<Collection<V>> {
+ private final DataExternalizer<V> myElementExternalizer;
+ private final CollectionFactory<V> myCollectionFactory;
+
+ public CollectionDataExternalizer(DataExternalizer<V> elementExternalizer,
+ CollectionFactory<V> collectionFactory) {
+ myElementExternalizer = elementExternalizer;
+ myCollectionFactory = collectionFactory;
+ }
+
+ @Override
+ public void save(final DataOutput out, final Collection<V> value) throws IOException {
+ for (V x : value) {
+ myElementExternalizer.save(out, x);
+ }
+ }
+
+ @Override
+ public Collection<V> read(final DataInput in) throws IOException {
+ final Collection<V> result = myCollectionFactory.create();
+ final DataInputStream stream = (DataInputStream)in;
+ while (stream.available() > 0) {
+ result.add(myElementExternalizer.read(in));
+ }
+ return result;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectTransientMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectTransientMultiMaplet.java
new file mode 100644
index 000000000000..a90281a5fb03
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectTransientMultiMaplet.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import gnu.trove.THashMap;
+import gnu.trove.TObjectHashingStrategy;
+import gnu.trove.TObjectObjectProcedure;
+
+import java.util.Collection;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/10/12
+ */
+public class ObjectObjectTransientMultiMaplet<K, V extends Streamable> extends ObjectObjectMultiMaplet<K, V>{
+
+ private final THashMap<K, Collection<V>> myMap;
+ private final CollectionFactory<V> myCollectionFactory;
+
+ public ObjectObjectTransientMultiMaplet(TObjectHashingStrategy<K> hashingStrategy, CollectionFactory<V> collectionFactory) {
+ myMap = new THashMap<K, Collection<V>>(hashingStrategy);
+ myCollectionFactory = collectionFactory;
+ }
+
+ @Override
+ public boolean containsKey(final K key) {
+ return myMap.containsKey(key);
+ }
+
+ @Override
+ public Collection<V> get(final K key) {
+ return myMap.get(key);
+ }
+
+ @Override
+ public void putAll(ObjectObjectMultiMaplet<K, V> m) {
+ m.forEachEntry(new TObjectObjectProcedure<K, Collection<V>>() {
+ @Override
+ public boolean execute(K key, Collection<V> value) {
+ put(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void put(final K key, final Collection<V> value) {
+ final Collection<V> x = myMap.get(key);
+ if (x == null) {
+ myMap.put(key, value);
+ }
+ else {
+ x.addAll(value);
+ }
+ }
+
+ @Override
+ public void replace(K key, Collection<V> value) {
+ if (value == null || value.isEmpty()) {
+ myMap.remove(key);
+ }
+ else {
+ myMap.put(key, value);
+ }
+ }
+
+ @Override
+ public void put(final K key, final V value) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection == null) {
+ final Collection<V> x = myCollectionFactory.create();
+ x.add(value);
+ myMap.put(key, x);
+ }
+ else {
+ collection.add(value);
+ }
+ }
+
+ @Override
+ public void removeFrom(final K key, final V value) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection != null) {
+ if (collection.remove(value)) {
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeAll(K key, Collection<V> values) {
+ final Collection<V> collection = myMap.get(key);
+ if (collection != null) {
+ if (collection.removeAll(values)) {
+ if (collection.isEmpty()) {
+ myMap.remove(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void remove(final K key) {
+ myMap.remove(key);
+ }
+
+ @Override
+ public void replaceAll(ObjectObjectMultiMaplet<K, V> m) {
+ m.forEachEntry(new TObjectObjectProcedure<K, Collection<V>>() {
+ @Override
+ public boolean execute(K key, Collection<V> value) {
+ replace(key, value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void forEachEntry(TObjectObjectProcedure<K, Collection<V>> procedure) {
+ myMap.forEachEntry(procedure);
+ }
+
+ @Override
+ public void close(){
+ myMap.clear(); // free memory
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/OrderProvider.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/OrderProvider.java
new file mode 100644
index 000000000000..06785fcbe0ad
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/OrderProvider.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * @author: db
+ * Date: 24.06.12
+ * Time: 19:08
+ * To change this template use File | Settings | File Templates.
+ */
+class OrderProvider {
+ private class Entry implements Comparable<Entry> {
+ final String myString;
+ final int myInt;
+
+ private Entry(int anInt) {
+ myInt = anInt;
+ myString = myContext.getValue(anInt);
+ }
+
+ @Override
+ public int compareTo(final Entry o) {
+ return o.myString.compareTo(myString);
+ }
+ }
+ private final DependencyContext myContext;
+ private final List<Entry> myList = new LinkedList<Entry>();
+
+ OrderProvider(final DependencyContext context) {
+ myContext = context;
+ }
+
+ void register (final int key) {
+ myList.add(new Entry(key));
+ }
+
+ int[] get() {
+ Collections.sort(myList);
+
+ final int[] result = new int[myList.size()];
+ int i = 0;
+
+ for (final Entry e : myList) {
+ result[i++] = e.myInt;
+ }
+
+ return result;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
new file mode 100644
index 000000000000..7a4351542bde
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import org.jetbrains.asm4.Opcodes;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.PrintStream;
+
+/**
+ * @author: db
+ * Date: 01.03.11
+ */
+class Proto implements RW.Savable, Streamable {
+ public final int access;
+ public final int signature;
+ public final int name;
+
+ protected Proto(final int access, final int signature, final int name) {
+ this.access = access;
+ this.signature = signature;
+ this.name = name;
+ }
+
+ protected Proto(final DataInput in) {
+ try {
+ access = in.readInt();
+ signature = in.readInt();
+ name = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeInt(access);
+ out.writeInt(signature);
+ out.writeInt(name);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Difference difference(final Proto past) {
+ int diff = Difference.NONE;
+
+ if (past.access != access) {
+ diff |= Difference.ACCESS;
+ }
+
+ if (past.signature != signature) {
+ diff |= Difference.SIGNATURE;
+ }
+
+ final int base = diff;
+
+ return new Difference() {
+ @Override
+ public int base() {
+ return base;
+ }
+
+ @Override
+ public boolean no() {
+ return base == NONE;
+ }
+
+ @Override
+ public int addedModifiers() {
+ return ~past.access & access;
+ }
+
+ @Override
+ public int removedModifiers() {
+ return ~access & past.access;
+ }
+
+ @Override
+ public boolean packageLocalOn() {
+ return ((past.access & Opcodes.ACC_PRIVATE) != 0 ||
+ (past.access & Opcodes.ACC_PUBLIC) != 0 ||
+ (past.access & Opcodes.ACC_PROTECTED) != 0) &&
+ Difference.isPackageLocal(access);
+ }
+
+ @Override
+ public boolean hadValue() {
+ return false;
+ }
+
+ @Override
+ public boolean weakedAccess() {
+ return Difference.weakerAccess(past.access, access);
+ }
+ };
+ }
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ final String d = this instanceof ClassRepr ? " " : " ";
+
+ if (this instanceof ClassRepr) {
+ stream.print(" Class ");
+ stream.println(context.getValue(name));
+ }
+
+ if (this instanceof MethodRepr) {
+ stream.print(" Method ");
+ stream.println(context.getValue(name));
+ }
+
+ if (this instanceof FieldRepr) {
+ stream.print(" Field ");
+ stream.println(context.getValue(name));
+ }
+
+ stream.print(d);
+ stream.print("Access : ");
+ stream.println(access);
+
+ stream.print(d);
+ stream.print("Signature : ");
+ stream.println(context.getValue(signature));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
new file mode 100644
index 000000000000..ff430e00e887
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import org.jetbrains.asm4.Type;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.PrintStream;
+
+/**
+ * @author: db
+ * Date: 07.03.11
+ */
+abstract class ProtoMember extends Proto {
+ private final static byte STRING = 0;
+ private final static byte NONE = 1;
+ private final static byte INTEGER = 2;
+ private final static byte LONG = 3;
+ private final static byte FLOAT = 4;
+ private final static byte DOUBLE = 5;
+ private final static byte TYPE = 6;
+
+ public final TypeRepr.AbstractType myType;
+ public final Object myValue;
+
+ public boolean hasValue() {
+ return myValue != null;
+ }
+
+ protected ProtoMember(final int access, final int signature, final int name, final TypeRepr.AbstractType t, final Object value) {
+ super(access, signature, name);
+ this.myType = t;
+ this.myValue = value;
+ }
+
+ private static Object loadTyped(final DataInput in) {
+ try {
+ switch (in.readByte()) {
+ case STRING:
+ return in.readUTF();
+ case NONE:
+ return null;
+ case INTEGER:
+ return in.readInt();
+ case LONG:
+ return in.readLong();
+ case FLOAT:
+ return in.readFloat();
+ case DOUBLE:
+ return in.readDouble();
+ case TYPE :
+ return Type.getType(in.readUTF());
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ assert (false);
+
+ return null;
+ }
+
+ protected ProtoMember(final DependencyContext context, final DataInput in) {
+ super(in);
+ try {
+ myType = TypeRepr.externalizer(context).read(in);
+ myValue = loadTyped(in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void save(final DataOutput out) {
+ super.save(out);
+ myType.save(out);
+
+ try {
+ if (myValue instanceof String) {
+ out.writeByte(STRING);
+ out.writeUTF((String)myValue);
+ }
+ else if (myValue instanceof Integer) {
+ out.writeByte(INTEGER);
+ out.writeInt(((Integer)myValue).intValue());
+ }
+ else if (myValue instanceof Long) {
+ out.writeByte(LONG);
+ out.writeLong(((Long)myValue).longValue());
+ }
+ else if (myValue instanceof Float) {
+ out.writeByte(FLOAT);
+ out.writeFloat(((Float)myValue).floatValue());
+ }
+ else if (myValue instanceof Double) {
+ out.writeByte(DOUBLE);
+ out.writeDouble(((Double)myValue).doubleValue());
+ }
+ else if (myValue instanceof Type) {
+ out.writeByte(TYPE);
+ out.writeUTF(((Type)myValue).getDescriptor());
+ }
+ else {
+ out.writeByte(NONE);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Difference difference(final Proto past) {
+ final ProtoMember m = (ProtoMember)past;
+ final Difference diff = super.difference(past);
+ int base = diff.base();
+
+ if (!m.myType.equals(myType)) {
+ base |= Difference.TYPE;
+ }
+
+ switch ((myValue == null ? 0 : 1) + (m.myValue == null ? 0 : 2)) {
+ case 3:
+ if (!myValue.equals(m.myValue)) {
+ base |= Difference.VALUE;
+ }
+ break;
+
+ case 2:
+ base |= Difference.VALUE;
+ break;
+
+ case 1:
+ base |= Difference.VALUE;
+ break;
+
+ case 0:
+ break;
+ }
+
+ final int newBase = base;
+
+ return new Difference() {
+ @Override
+ public int base() {
+ return newBase;
+ }
+
+ @Override
+ public boolean no() {
+ return newBase == NONE && diff.no();
+ }
+
+ @Override
+ public int addedModifiers() {
+ return diff.addedModifiers();
+ }
+
+ @Override
+ public int removedModifiers() {
+ return diff.removedModifiers();
+ }
+
+ @Override
+ public boolean packageLocalOn() {
+ return diff.packageLocalOn();
+ }
+
+ @Override
+ public boolean hadValue() {
+ return ((ProtoMember)past).hasValue();
+ }
+
+ @Override
+ public boolean weakedAccess() {
+ return diff.weakedAccess();
+ }
+ };
+ }
+
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ super.toStream(context, stream);
+ stream.print(" Type : ");
+ stream.println(myType.getDescr(context));
+
+ stream.print(" Value : ");
+ stream.println(myValue == null ? "<null>" : myValue.toString());
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
new file mode 100644
index 000000000000..43871811a47b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.io.DataExternalizer;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntProcedure;
+
+import java.io.*;
+import java.util.Collection;
+
+/**
+ * @author: db
+ * Date: 29.01.11
+ */
+public class RW {
+ private RW() {
+
+ }
+
+ public interface Savable {
+ void save(DataOutput out);
+ }
+
+ public static <X extends Savable> void save(final X[] x, final DataOutput out) {
+ try {
+ out.writeInt(x.length);
+ for (Savable s : x) {
+ s.save(out);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static <X> void save(final TIntHashSet x, final DataOutput out) {
+ try {
+ out.writeInt(x.size());
+ x.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ try {
+ out.writeInt(value);
+ return true;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ catch (IOException c) {
+ throw new RuntimeException(c);
+ }
+ }
+
+ public static <X> void save(final Collection<X> x, final DataExternalizer<X> e, final DataOutput out) {
+ try {
+ out.writeInt(x.size());
+
+ for (X y : x) {
+ e.save(out, y);
+ }
+ }
+ catch (IOException c) {
+ throw new RuntimeException(c);
+ }
+ }
+
+ public static <X extends Savable> void save(final Collection<X> x, final DataOutput out) {
+ try {
+ final int size = x.size();
+
+ out.writeInt(size);
+
+ for (X s : x) {
+ s.save(out);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static <X> X[] read(final DataExternalizer<X> e, final DataInput in, final X[] result) {
+ try {
+ for (int i = 0; i < result.length; i++) {
+ result[i] = e.read(in);
+ }
+
+ return result;
+ }
+ catch (IOException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ public static TIntHashSet read(final TIntHashSet acc, final DataInput in) {
+ try {
+ final int size = in.readInt();
+
+ for (int i = 0; i<size; i++) {
+ acc.add(in.readInt());
+ }
+
+ return acc;
+ }
+ catch (IOException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ public static <X> Collection<X> read(final DataExternalizer<X> e, final Collection<X> acc, final DataInput in) {
+ try {
+ final int size = in.readInt();
+
+ for (int i = 0; i<size; i++) {
+ acc.add(e.read(in));
+ }
+
+ return acc;
+ }
+ catch (IOException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ public interface Writable {
+ void write(BufferedWriter w);
+ }
+
+ public static <T extends Comparable> void writeln(final BufferedWriter w, final Collection<T> c, final ToWritable<T> t) {
+ if (c == null) {
+ writeln(w, "0");
+ return;
+ }
+
+ writeln(w, Integer.toString(c.size()));
+
+ for (T e : c) {
+ t.convert(e).write(w);
+ }
+ }
+
+ public static void writeln(final BufferedWriter w, final Collection<? extends Writable> c) {
+ if (c == null) {
+ writeln(w, "0");
+ return;
+ }
+
+ writeln(w, Integer.toString(c.size()));
+
+ for (Writable e : c) {
+ e.write(w);
+ }
+ }
+
+ public interface ToWritable<T> {
+ Writable convert(T x);
+ }
+
+ public static void writeln(final BufferedWriter w, final String s) {
+ try {
+ if (s == null) {
+ w.write("");
+ }
+ else {
+ w.write(s);
+ }
+ w.newLine();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public interface Reader<T> {
+ T read(BufferedReader r);
+ }
+
+ public static ToWritable<String> fromString = new ToWritable<String>() {
+ public Writable convert(final String s) {
+ return new Writable() {
+ public void write(BufferedWriter w) {
+ writeln(w, s);
+ }
+ };
+ }
+ };
+
+ public static Reader<String> myStringReader = new Reader<String>() {
+ public String read(final BufferedReader r) {
+ try {
+ return r.readLine();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ public static <T> Collection<T> readMany(final BufferedReader r, final Reader<T> c, final Collection<T> acc) {
+ final int size = readInt(r);
+
+ for (int i = 0; i < size; i++) {
+ acc.add(c.read(r));
+ }
+
+ return acc;
+ }
+
+ public static String lookString(final BufferedReader r) {
+ try {
+ r.mark(256);
+ final String s = r.readLine();
+ r.reset();
+
+ return s;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void readTag(final BufferedReader r, final String tag) {
+ try {
+ final String s = r.readLine();
+
+ if (!s.equals(tag)) System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String readString(final BufferedReader r) {
+ try {
+ return r.readLine();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static long readLong(final BufferedReader r) {
+ final String s = readString(r);
+
+ try {
+ return Long.parseLong(s);
+ }
+ catch (Exception n) {
+ System.err.println("Parsing error: expected long, but found \"" + s + "\"");
+ return 0;
+ }
+ }
+
+ public static int readInt(final BufferedReader r) {
+ final String s = readString(r);
+
+ try {
+ return Integer.parseInt(s);
+ }
+ catch (Exception n) {
+ System.err.println("Parsing error: expected integer, but found \"" + s + "\"");
+ return 0;
+ }
+ }
+
+ public static String readStringAttribute(final BufferedReader r, final String tag) {
+ try {
+ final String s = r.readLine();
+
+ if (s.startsWith(tag)) return s.substring(tag.length());
+
+ System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
+
+ return null;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Streamable.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Streamable.java
new file mode 100644
index 000000000000..ddbc937cdba3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Streamable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import java.io.PrintStream;
+
+/**
+ * Created with IntelliJ IDEA.
+ * @author: db
+ * Date: 24.04.12
+ * Time: 0:44
+ * To change this template use File | Settings | File Templates.
+ */
+
+interface Streamable {
+ void toStream(DependencyContext context, PrintStream stream);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
new file mode 100644
index 000000000000..3a9fb53c6326
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.asm4.Type;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * @author: db
+ * Date: 14.02.11
+ */
+class TypeRepr {
+ private static final byte PRIMITIVE_TYPE = 0x0;
+ private static final byte CLASS_TYPE = 0x1;
+ private static final byte ARRAY_TYPE = 0x2;
+
+ private TypeRepr() {
+
+ }
+
+ interface AbstractType extends RW.Savable {
+ AbstractType[] EMPTY_TYPE_ARRAY = new AbstractType[0];
+
+ void updateClassUsages(DependencyContext context, int owner, Set<UsageRepr.Usage> s);
+ String getDescr(DependencyContext context);
+ void save(DataOutput out);
+ }
+
+ public static class PrimitiveType implements AbstractType {
+ public final int type;
+
+ @Override
+ public String getDescr(final DependencyContext context) {
+ return context.getValue(type);
+ }
+
+ @Override
+ public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
+
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(PRIMITIVE_TYPE);
+ out.writeInt(type);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ PrimitiveType(final int type) {
+ this.type = type;
+ }
+
+ PrimitiveType(final DataInput in) {
+ try {
+ type = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final PrimitiveType that = (PrimitiveType)o;
+
+ return type == that.type;
+ }
+
+ @Override
+ public int hashCode() {
+ return type;
+ }
+ }
+
+ public static class ArrayType implements AbstractType {
+ public final AbstractType elementType;
+
+ public AbstractType getDeepElementType() {
+ AbstractType current = this;
+
+ while (current instanceof ArrayType) {
+ current = ((ArrayType)current).elementType;
+ }
+
+ return current;
+ }
+
+ @Override
+ public String getDescr(final DependencyContext context) {
+ return "[" + elementType.getDescr(context);
+ }
+
+ @Override
+ public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
+ elementType.updateClassUsages(context, owner, s);
+ }
+
+ ArrayType(final AbstractType elementType) {
+ this.elementType = elementType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ArrayType arrayType = (ArrayType)o;
+
+ return elementType.equals(arrayType.elementType);
+ }
+
+ @Override
+ public int hashCode() {
+ return elementType.hashCode();
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(ARRAY_TYPE);
+ elementType.save(out);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static class ClassType implements AbstractType {
+ public final int className;
+ public final AbstractType[] typeArgs;
+
+ @Override
+ public String getDescr(final DependencyContext context) {
+ return "L" + context.getValue(className) + ";";
+ }
+
+ @Override
+ public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
+ s.add(UsageRepr.createClassUsage(context, className));
+ }
+
+ ClassType(final int className) {
+ this.className = className;
+ typeArgs = EMPTY_TYPE_ARRAY;
+ }
+
+ ClassType(final DependencyContext context, final DataInput in) {
+ try {
+ className = in.readInt();
+ final int size = in.readInt();
+ if (size == 0) {
+ typeArgs = EMPTY_TYPE_ARRAY;
+ }
+ else {
+ typeArgs = new AbstractType[size];
+ final DataExternalizer<AbstractType> externalizer = externalizer(context);
+ for (int i = 0; i < size; i++) {
+ typeArgs[i] = externalizer.read(in);
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ClassType classType = (ClassType)o;
+
+ if (className != classType.className) return false;
+ if (!Arrays.equals(typeArgs, classType.typeArgs)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = className;
+ result = 31 * result + (typeArgs != null ? Arrays.hashCode(typeArgs) : 0);
+ return result;
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(CLASS_TYPE);
+ out.writeInt(className);
+ out.writeInt(typeArgs.length);
+ for (AbstractType t : typeArgs) {
+ t.save(out);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static Collection<AbstractType> createClassType(final DependencyContext context,
+ final String[] args,
+ final Collection<AbstractType> acc) {
+ if (args != null) {
+ for (String a : args) {
+ acc.add(createClassType(context, context.get(a)));
+ }
+ }
+
+ return acc;
+ }
+
+ public static Collection<AbstractType> createClassType(final DependencyContext context,
+ final Collection<String> args,
+ final Collection<AbstractType> acc) {
+ if (args != null) {
+ for (String a : args) {
+ acc.add(createClassType(context, context.get(a)));
+ }
+ }
+
+ return acc;
+ }
+
+ public static ClassType createClassType(final DependencyContext context, final int s) {
+ return (ClassType)context.getType(new ClassType(s));
+ }
+
+ public static AbstractType getType(final DependencyContext context, final int descr) {
+ final Type t = Type.getType(context.getValue(descr));
+
+ switch (t.getSort()) {
+ case Type.OBJECT:
+ return context.getType(new ClassType(context.get(StringUtil.replaceChar(t.getClassName(), '.', '/'))));
+
+ case Type.ARRAY:
+ return context.getType(new ArrayType(getType(context, t.getElementType())));
+
+ default:
+ return context.getType(new PrimitiveType(descr));
+ }
+ }
+
+ public static AbstractType getType(final DependencyContext context, final Type t) {
+ return getType(context, context.get(t.getDescriptor()));
+ }
+
+ public static AbstractType[] getType(final DependencyContext context, final Type[] t) {
+ final AbstractType[] r = new AbstractType[t.length];
+
+ for (int i = 0; i < r.length; i++) {
+ r[i] = getType(context, t[i]);
+ }
+
+ return r;
+ }
+
+ public static DataExternalizer<AbstractType> externalizer(final DependencyContext context) {
+ return new DataExternalizer<AbstractType>() {
+ @Override
+ public void save(final DataOutput out, final AbstractType value) throws IOException {
+ value.save(out);
+ }
+
+ @Override
+ public AbstractType read(final DataInput in) throws IOException {
+ AbstractType elementType;
+ int level = 0;
+
+ loop:
+ while (true) {
+ final byte tag = in.readByte();
+ switch (tag) {
+ case PRIMITIVE_TYPE:
+ elementType = context.getType(new PrimitiveType(in));
+ break loop;
+
+ case CLASS_TYPE:
+ elementType = context.getType(new ClassType(context, in));
+ break loop;
+
+ case ARRAY_TYPE:
+ level++;
+ break;
+
+ default :
+ System.out.println("Unknown type!");
+ }
+ }
+
+ for (int i = 0; i < level; i++) {
+ elementType = context.getType(new ArrayType(elementType));
+ }
+
+ return elementType;
+ }
+ };
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
new file mode 100644
index 000000000000..abe9df363ba6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
@@ -0,0 +1,746 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java.dependencyView;
+
+import com.intellij.util.io.DataExternalizer;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntProcedure;
+import org.jetbrains.asm4.Type;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * @author: db
+ * Date: 14.02.11
+ */
+class UsageRepr {
+ private static final byte FIELD_USAGE = 0x0;
+ private static final byte FIELD_ASSIGN_USAGE = 0x1;
+ private static final byte METHOD_USAGE = 0x2;
+ private static final byte CLASS_USAGE = 0x3;
+ private static final byte CLASS_EXTENDS_USAGE = 0x4;
+ private static final byte CLASS_NEW_USAGE = 0x5;
+ private static final byte ANNOTATION_USAGE = 0x6;
+ private static final byte METAMETHOD_USAGE = 0x7;
+ private static final byte CLASS_AS_GENERIC_BOUND_USAGE = 0x8;
+
+ private static final int DEFAULT_SET_CAPACITY = 32;
+ private static final float DEFAULT_SET_LOAD_FACTOR = 0.98f;
+
+ private UsageRepr() {
+
+ }
+
+ public static abstract class Usage implements RW.Savable, Streamable {
+ public abstract int getOwner();
+ }
+
+ public static abstract class FMUsage extends Usage {
+ public final int myName;
+ public final int myOwner;
+
+ abstract void kindToStream (PrintStream stream);
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ kindToStream(stream);
+ stream.println(" Name : " + context.getValue(myName));
+ stream.println(" Owner: " + context.getValue(myOwner));
+ }
+
+ @Override
+ public int getOwner() {
+ return myOwner;
+ }
+
+ private FMUsage(final int name, final int owner) {
+ this.myName = name;
+ this.myOwner = owner;
+ }
+
+ private FMUsage(final DataInput in) {
+ try {
+ myName = in.readInt();
+ myOwner = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected final void save(final byte tag, final DataOutput out) {
+ try {
+ out.writeByte(tag);
+ out.writeInt(myName);
+ out.writeInt(myOwner);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FMUsage fmUsage = (FMUsage)o;
+
+ if (myName != fmUsage.myName) return false;
+ if (myOwner != fmUsage.myOwner) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * myName + myOwner;
+ }
+ }
+
+ public static class FieldUsage extends FMUsage {
+ public final TypeRepr.AbstractType myType;
+
+ private FieldUsage(final DependencyContext context, final int name, final int owner, final int descriptor) {
+ super(name, owner);
+ myType = TypeRepr.getType(context, descriptor);
+ }
+
+ private FieldUsage(final DependencyContext context, final DataInput in) {
+ super(in);
+ try {
+ myType = TypeRepr.externalizer(context).read(in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void kindToStream(final PrintStream stream) {
+ stream.println("FieldUsage:");
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ super.toStream(context, stream);
+ stream.println(" Type: " + myType.getDescr(context));
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ save(FIELD_USAGE, out);
+ myType.save(out);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final FieldUsage that = (FieldUsage)o;
+
+ return myType.equals(that.myType) && myName == that.myName && myOwner == that.myOwner;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * (31 * myType.hashCode() + myName) + myOwner;
+ }
+ }
+
+ public static class FieldAssignUsage extends FieldUsage {
+ private FieldAssignUsage(final DependencyContext context, final int n, final int o, final int d) {
+ super(context, n, o, d);
+ }
+
+ private FieldAssignUsage(final DependencyContext context, final DataInput in) {
+ super(context, in);
+ }
+
+ @Override
+ protected void kindToStream(final PrintStream stream) {
+ stream.println("FieldAssignUsage:");
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ save(FIELD_ASSIGN_USAGE, out);
+ myType.save(out);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final FieldAssignUsage that = (FieldAssignUsage)o;
+
+ return myType.equals(that.myType) && myName == that.myName && myOwner == that.myOwner;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + 1;
+ }
+ }
+
+ public static class MethodUsage extends FMUsage {
+ public final TypeRepr.AbstractType[] myArgumentTypes;
+ public final TypeRepr.AbstractType myReturnType;
+
+ private MethodUsage(final DependencyContext context, final int name, final int owner, final String descriptor) {
+ super(name, owner);
+ myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(descriptor));
+ myReturnType = TypeRepr.getType(context, Type.getReturnType(descriptor));
+ }
+
+ private MethodUsage(final DependencyContext context, final DataInput in) {
+ super(in);
+ try {
+ final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
+ myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[in.readInt()]);
+ myReturnType = externalizer.read(in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ save(METHOD_USAGE, out);
+ RW.save(myArgumentTypes, out);
+ myReturnType.save(out);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodUsage that = (MethodUsage)o;
+
+ if (!Arrays.equals(myArgumentTypes, that.myArgumentTypes)) return false;
+ if (myReturnType != null ? !myReturnType.equals(that.myReturnType) : that.myReturnType != null) return false;
+ if (myName != that.myName) return false;
+ if (myOwner != that.myOwner) return false;
+
+ return Arrays.equals(myArgumentTypes, that.myArgumentTypes) &&
+ myReturnType.equals(that.myReturnType) &&
+ myName == that.myName &&
+ myOwner == that.myOwner;
+ }
+
+ @Override
+ public int hashCode() {
+ return ((31 * Arrays.hashCode(myArgumentTypes) + (myReturnType.hashCode())) * 31 + (myName)) * 31 + (myOwner);
+ }
+
+ @Override
+ void kindToStream(final PrintStream stream) {
+ stream.println("MethodUsage:");
+ }
+
+ @Override
+ public void toStream(DependencyContext context, PrintStream stream) {
+ super.toStream(context, stream);
+
+ stream.println(" Arguments:");
+
+ for (final TypeRepr.AbstractType at : myArgumentTypes) {
+ stream.println(" " + at.getDescr(context));
+ }
+
+ stream.println(" Return type:");
+ stream.println(" " + myReturnType.getDescr(context));
+ }
+ }
+
+ public static class MetaMethodUsage extends FMUsage {
+ private int myArity;
+
+ public MetaMethodUsage(final DependencyContext context, final int n, final int o, final String descr) {
+ super(n, o);
+ myArity = TypeRepr.getType(context, Type.getArgumentTypes(descr)).length;
+ }
+
+ public MetaMethodUsage(final DataInput in) {
+ super(in);
+ try {
+ myArity = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ save(METAMETHOD_USAGE, out);
+ try {
+ out.writeInt(myArity);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ MetaMethodUsage that = (MetaMethodUsage)o;
+
+ if (myArity != that.myArity) return false;
+
+ return super.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + myArity;
+ return result;
+ }
+
+ @Override
+ void kindToStream(final PrintStream stream) {
+ stream.println("MetaMethodUsage:");
+ }
+
+ @Override
+ public void toStream(DependencyContext context, PrintStream stream) {
+ super.toStream(context, stream);
+ stream.println(" Arity: " + Integer.toString(myArity));
+ }
+ }
+
+ public static class ClassUsage extends Usage {
+ final int myClassName;
+
+ @Override
+ public int getOwner() {
+ return myClassName;
+ }
+
+ private ClassUsage(final int className) {
+ this.myClassName = className;
+ }
+
+ private ClassUsage(final DataInput in) {
+ try {
+ myClassName = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(CLASS_USAGE);
+ out.writeInt(myClassName);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ClassUsage that = (ClassUsage)o;
+
+ return myClassName == that.myClassName;
+ }
+
+ @Override
+ public int hashCode() {
+ return myClassName;
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ stream.println("ClassUsage: " + context.getValue(myClassName));
+ }
+ }
+
+ public static class ClassAsGenericBoundUsage extends ClassUsage {
+ public ClassAsGenericBoundUsage(int className) {
+ super(className);
+ }
+
+ public ClassAsGenericBoundUsage(DataInput in) {
+ super(in);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + 3;
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(CLASS_AS_GENERIC_BOUND_USAGE);
+ out.writeInt(myClassName);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static class ClassExtendsUsage extends Usage {
+ protected final int myClassName;
+
+ @Override
+ public int getOwner() {
+ return myClassName;
+ }
+
+ private ClassExtendsUsage(final int className) {
+ this.myClassName = className;
+ }
+
+ private ClassExtendsUsage(final DataInput in) {
+ try {
+ myClassName = in.readInt();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(CLASS_EXTENDS_USAGE);
+ out.writeInt(myClassName);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return myClassName + 1;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ClassExtendsUsage that = (ClassExtendsUsage)o;
+
+ if (myClassName != that.myClassName) return false;
+
+ return true;
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ stream.println("ClassExtendsUsage: " + context.getValue(myClassName));
+ }
+ }
+
+ public static class ClassNewUsage extends ClassExtendsUsage {
+ public ClassNewUsage(int className) {
+ super(className);
+ }
+
+ private ClassNewUsage(final DataInput in) {
+ super(in);
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(CLASS_NEW_USAGE);
+ out.writeInt(myClassName);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return myClassName + 2;
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ stream.println("ClassNewUsage: " + context.getValue(myClassName));
+ }
+ }
+
+ public static class AnnotationUsage extends Usage {
+ public static final DataExternalizer<ElemType> elementTypeExternalizer = new DataExternalizer<ElemType>() {
+ @Override
+ public void save(final DataOutput out, final ElemType value) throws IOException {
+ out.writeInt(value.ordinal());
+ }
+
+ @Override
+ public ElemType read(final DataInput in) throws IOException {
+ final int ordinal = in.readInt();
+ for (ElemType value : ElemType.values()) {
+ if (value.ordinal() == ordinal) {
+ return value;
+ }
+ }
+ throw new IOException("Error reading ElementType enum value; unknown ordinal: " + ordinal);
+ }
+ };
+
+ final TypeRepr.ClassType myType;
+ final TIntHashSet myUsedArguments;
+ final Set<ElemType> myUsedTargets;
+
+ public boolean satisfies(final Usage usage) {
+ if (usage instanceof AnnotationUsage) {
+ final AnnotationUsage annotationUsage = (AnnotationUsage)usage;
+
+ if (!myType.equals(annotationUsage.myType)) {
+ return false;
+ }
+
+ boolean argumentsSatisfy = false;
+
+ if (myUsedArguments != null) {
+ final TIntHashSet arguments = new TIntHashSet(myUsedArguments.toArray());
+
+ arguments.removeAll(annotationUsage.myUsedArguments.toArray());
+
+ argumentsSatisfy = !arguments.isEmpty();
+ }
+
+ boolean targetsSatisfy = false;
+
+ if (myUsedTargets != null) {
+ final Collection<ElemType> targets = EnumSet.copyOf(myUsedTargets);
+
+ targets.retainAll(annotationUsage.myUsedTargets);
+
+ targetsSatisfy = !targets.isEmpty();
+ }
+
+ return argumentsSatisfy || targetsSatisfy;
+ }
+
+ return false;
+ }
+
+ private AnnotationUsage(final TypeRepr.ClassType type, final TIntHashSet usedArguments, final Set<ElemType> targets) {
+ this.myType = type;
+ this.myUsedArguments = usedArguments;
+ this.myUsedTargets = targets;
+ }
+
+ private AnnotationUsage(final DependencyContext context, final DataInput in) {
+ final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
+
+ try {
+ myType = (TypeRepr.ClassType)externalizer.read(in);
+ myUsedArguments = RW.read(new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR), in);
+ myUsedTargets = (EnumSet<ElemType>)RW.read(elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void save(final DataOutput out) {
+ try {
+ out.writeByte(ANNOTATION_USAGE);
+ myType.save(out);
+ RW.save(myUsedArguments, out);
+ RW.save(myUsedTargets, elementTypeExternalizer, out);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int getOwner() {
+ return myType.className;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AnnotationUsage that = (AnnotationUsage)o;
+
+ if (myUsedArguments != null ? !myUsedArguments.equals(that.myUsedArguments) : that.myUsedArguments != null) return false;
+ if (myUsedTargets != null ? !myUsedTargets.equals(that.myUsedTargets) : that.myUsedTargets != null) return false;
+ if (myType != null ? !myType.equals(that.myType) : that.myType != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myType != null ? myType.hashCode() : 0;
+ result = 31 * result + (myUsedArguments != null ? myUsedArguments.hashCode() : 0);
+ result = 31 * result + (myUsedTargets != null ? myUsedTargets.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public void toStream(final DependencyContext context, final PrintStream stream) {
+ stream.println(" AnnotationUsage:");
+ stream.println(" Type : " + myType.getDescr(context));
+
+ final List<String> arguments = new LinkedList<String>();
+
+ if (myUsedArguments != null) {
+ myUsedArguments.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int value) {
+ arguments.add(context.getValue(value));
+ return true;
+ }
+ });
+ }
+
+ Collections.sort(arguments);
+
+ final List<String> targets = new LinkedList<String>();
+
+ if (myUsedTargets != null) {
+ for (final ElemType e : myUsedTargets) {
+ targets.add(e.toString());
+ }
+ }
+
+ Collections.sort(targets);
+
+ stream.println(" Arguments:");
+
+ for (final String s : arguments) {
+ stream.println(" " + s);
+ }
+
+ stream.println(" Targets :");
+
+ for (final String s : targets) {
+ stream.println(" " + s);
+ }
+ }
+ }
+
+ public static Usage createFieldUsage(final DependencyContext context, final int name, final int owner, final int descr) {
+ return context.getUsage(new FieldUsage(context, name, owner, descr));
+ }
+
+ public static Usage createFieldAssignUsage(final DependencyContext context, final int name, final int owner, final int descr) {
+ return context.getUsage(new FieldAssignUsage(context, name, owner, descr));
+ }
+
+ public static Usage createMethodUsage(final DependencyContext context, final int name, final int owner, final String descr) {
+ return context.getUsage(new MethodUsage(context, name, owner, descr));
+ }
+
+ public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner, final String descr) {
+ return context.getUsage(new MetaMethodUsage(context, name, owner, descr));
+ }
+
+ public static Usage createClassUsage(final DependencyContext context, final int name) {
+ return context.getUsage(new ClassUsage(name));
+ }
+
+ public static Usage createClassAsGenericBoundUsage(final DependencyContext context, final int name) {
+ return context.getUsage(new ClassAsGenericBoundUsage(name));
+ }
+
+
+ public static Usage createClassExtendsUsage(final DependencyContext context, final int name) {
+ return context.getUsage(new ClassExtendsUsage(name));
+ }
+
+ public static Usage createClassNewUsage(final DependencyContext context, final int name) {
+ return context.getUsage(new ClassNewUsage(name));
+ }
+
+ public static Usage createAnnotationUsage(final DependencyContext context,
+ final TypeRepr.ClassType type,
+ final TIntHashSet usedArguments,
+ final Set<ElemType> targets) {
+ return context.getUsage(new AnnotationUsage(type, usedArguments, targets));
+ }
+
+ public static DataExternalizer<Usage> externalizer(final DependencyContext context) {
+ return new DataExternalizer<Usage>() {
+ @Override
+ public void save(final DataOutput out, final Usage value) throws IOException {
+ value.save(out);
+ }
+
+ @Override
+ public Usage read(DataInput in) throws IOException {
+ final byte tag = in.readByte();
+ switch (tag) {
+ case CLASS_USAGE:
+ return context.getUsage(new ClassUsage(in));
+
+ case CLASS_AS_GENERIC_BOUND_USAGE:
+ return context.getUsage(new ClassAsGenericBoundUsage(in));
+
+ case CLASS_EXTENDS_USAGE:
+ return context.getUsage(new ClassExtendsUsage(in));
+
+ case CLASS_NEW_USAGE:
+ return context.getUsage(new ClassNewUsage(in));
+
+ case FIELD_USAGE:
+ return context.getUsage(new FieldUsage(context, in));
+
+ case FIELD_ASSIGN_USAGE:
+ return context.getUsage(new FieldAssignUsage(context, in));
+
+ case METHOD_USAGE:
+ return context.getUsage(new MethodUsage(context, in));
+
+ case ANNOTATION_USAGE:
+ return context.getUsage(new AnnotationUsage(context, in));
+
+ case METAMETHOD_USAGE:
+ return context.getUsage(new MetaMethodUsage(in));
+ }
+
+ assert (false);
+
+ return null;
+ }
+ };
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java
new file mode 100644
index 000000000000..42cc7d735bf0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.logging;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerImpl;
+
+/**
+ * @author nik
+ */
+public class BuildLoggingManager {
+ public static final BuildLoggingManager DEFAULT = new BuildLoggingManager(new ProjectBuilderLoggerImpl());
+ private final ProjectBuilderLogger myProjectLogger;
+
+ public BuildLoggingManager(@NotNull ProjectBuilderLogger projectLogger) {
+ myProjectLogger = projectLogger;
+ }
+
+ @NotNull
+ public ProjectBuilderLogger getProjectBuilderLogger() {
+ return myProjectLogger;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java
new file mode 100644
index 000000000000..8302ee4df721
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.logging;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface ProjectBuilderLogger {
+ boolean isEnabled();
+
+ void logDeletedFiles(Collection<String> paths);
+
+ void logCompiledFiles(Collection<File> files, String builderName, String description) throws IOException;
+
+ void logCompiledPaths(Collection<String> paths, String builderName, String description) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java
new file mode 100644
index 000000000000..fa5e3fb1ed0f
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.storage;
+
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetType;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface BuildDataPaths {
+ File getDataStorageRoot();
+
+ File getTargetsDataRoot();
+
+ File getTargetTypeDataRoot(BuildTargetType<?> targetType);
+
+ File getTargetDataRoot(BuildTarget<?> target);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java
new file mode 100644
index 000000000000..f0905d95feb8
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.storage;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * @author nik
+ */
+public interface SourceToOutputMapping {
+ void setOutputs(@NotNull String srcPath, @NotNull Collection<String> outputs) throws IOException;
+
+ void setOutput(@NotNull String srcPath, @NotNull String outputPath) throws IOException;
+
+ void appendOutput(@NotNull String srcPath, @NotNull String outputPath) throws IOException;
+
+
+ void remove(@NotNull String srcPath) throws IOException;
+
+ void removeOutput(@NotNull String sourcePath, @NotNull String outputPath) throws IOException;
+
+
+ @NotNull
+ Collection<String> getSources() throws IOException;
+
+ @Nullable
+ Collection<String> getOutputs(@NotNull String srcPath) throws IOException;
+
+ @NotNull
+ Iterator<String> getSourcesIterator() throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/storage/StorageProvider.java b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/StorageProvider.java
new file mode 100644
index 000000000000..5c82ed613862
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/StorageProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.storage;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.storage.StorageOwner;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public abstract class StorageProvider<S extends StorageOwner> {
+ @NotNull
+ public abstract S createStorage(File targetDataDir) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
new file mode 100644
index 000000000000..1134d30e197e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.client;
+
+import com.google.protobuf.MessageLite;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.api.RequestFuture;
+
+import java.util.ArrayList;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/22/12
+*/
+final class ProtobufClientMessageHandler<T extends ProtobufResponseHandler> extends SimpleChannelHandler {
+ private final ConcurrentHashMap<UUID, RequestFuture<T>> myHandlers = new ConcurrentHashMap<UUID, RequestFuture<T>>();
+ @NotNull
+ private final UUIDGetter myUuidGetter;
+ private final SimpleProtobufClient myClient;
+ private final Executor myAsyncExec;
+
+ public ProtobufClientMessageHandler(@NotNull UUIDGetter uuidGetter, SimpleProtobufClient client, Executor asyncExec) {
+ myUuidGetter = uuidGetter;
+ myClient = client;
+ myAsyncExec = asyncExec;
+ }
+
+ public final void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ final UUID messageUUID = myUuidGetter.getSessionUUID(e);
+ final RequestFuture<T> future = myHandlers.get(messageUUID);
+ final T handler = future != null ? future.getMessageHandler() : null;
+ if (handler == null) {
+ terminateSession(messageUUID);
+ }
+ else {
+ boolean terminateSession = false;
+ try {
+ terminateSession = handler.handleMessage((MessageLite)e.getMessage());
+ }
+ catch (Exception ex) {
+ terminateSession = true;
+ throw ex;
+ }
+ finally {
+ if (terminateSession) {
+ terminateSession(messageUUID);
+ }
+ }
+ }
+ }
+
+ private void terminateSession(UUID sessionId) {
+ final RequestFuture<T> future = removeFuture(sessionId);
+ if (future != null) {
+ final T handler = future.getMessageHandler();
+ try {
+ if (handler != null) {
+ try {
+ handler.sessionTerminated();
+ }
+ catch (Throwable ignored) {
+ ignored.printStackTrace();
+ }
+ }
+ }
+ finally {
+ future.setDone();
+ }
+ }
+ }
+
+ public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ try {
+ super.channelClosed(ctx, e);
+ }
+ finally {
+ for (UUID uuid : new ArrayList<UUID>(myHandlers.keySet())) {
+ terminateSession(uuid);
+ }
+ }
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ try {
+ super.channelDisconnected(ctx, e);
+ }
+ finally {
+ // make sure the client is in disconnected state
+ myAsyncExec.execute(new Runnable() {
+ @Override
+ public void run() {
+ myClient.disconnect();
+ }
+ });
+ }
+ }
+
+ public void registerFuture(UUID messageId, RequestFuture<T> requestFuture) {
+ myHandlers.put(messageId, requestFuture);
+ }
+
+ public RequestFuture<T> removeFuture(UUID messageId) {
+ return myHandlers.remove(messageId);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufResponseHandler.java b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufResponseHandler.java
new file mode 100644
index 000000000000..ef9a6035e77f
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufResponseHandler.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.client;
+
+import com.google.protobuf.MessageLite;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/22/12
+ */
+public interface ProtobufResponseHandler {
+
+ /**
+ * @param message
+ * @return true if session should be terminated, false otherwise
+ * @throws Exception
+ */
+ boolean handleMessage(MessageLite message) throws Exception;
+
+ void sessionTerminated();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java
new file mode 100644
index 000000000000..06f41756fd03
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.client;
+
+import com.google.protobuf.MessageLite;
+import com.intellij.openapi.diagnostic.Logger;
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.*;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.RequestFuture;
+
+import java.net.InetSocketAddress;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/22/12
+ */
+public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.client.SimpleProtobufClient");
+
+ private static enum State {
+ DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING
+ }
+
+ private final AtomicReference<State> myState = new AtomicReference<State>(State.DISCONNECTED);
+ protected final ChannelPipelineFactory myPipelineFactory;
+ protected final ChannelFactory myChannelFactory;
+ protected volatile ChannelFuture myConnectFuture;
+ private final ProtobufClientMessageHandler<T> myMessageHandler;
+
+ public SimpleProtobufClient(final MessageLite msgDefaultInstance, final Executor asyncExec, final UUIDGetter uuidGetter) {
+ myMessageHandler = new ProtobufClientMessageHandler<T>(uuidGetter, this, asyncExec);
+ myChannelFactory = new NioClientSocketChannelFactory(asyncExec, asyncExec, 1);
+ myPipelineFactory = new ChannelPipelineFactory() {
+ public ChannelPipeline getPipeline() throws Exception {
+ return Channels.pipeline(
+ new ProtobufVarint32FrameDecoder(),
+ new ProtobufDecoder(msgDefaultInstance),
+ new ProtobufVarint32LengthFieldPrepender(),
+ new ProtobufEncoder(),
+ myMessageHandler
+ );
+ }
+ };
+ }
+
+ public final void checkConnected() throws Exception {
+ if (myState.get() != State.CONNECTED) {
+ throw new Exception("Client not connected");
+ }
+ }
+
+ public final boolean connect(final String host, final int port) throws Throwable {
+ if (myState.compareAndSet(State.DISCONNECTED, State.CONNECTING)) {
+ boolean success = false;
+
+ try {
+ final ClientBootstrap bootstrap = new ClientBootstrap(myChannelFactory);
+ bootstrap.setPipelineFactory(myPipelineFactory);
+ bootstrap.setOption("tcpNoDelay", true);
+ bootstrap.setOption("keepAlive", true);
+ final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
+ future.awaitUninterruptibly();
+
+ success = future.isSuccess();
+
+ if (success) {
+ myConnectFuture = future;
+ try {
+ onConnect();
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+ else {
+ final Throwable reason = future.getCause();
+ if (reason != null) {
+ throw reason;
+ }
+ }
+
+ return success;
+ }
+ finally {
+ myState.compareAndSet(State.CONNECTING, success? State.CONNECTED : State.DISCONNECTED);
+ }
+ }
+ // already connected
+ return true;
+ }
+
+ protected void onConnect() {
+ }
+ protected void beforeDisconnect() {
+ }
+ protected void onDisconnect() {
+ }
+
+ public final void disconnect() {
+ if (myState.compareAndSet(State.CONNECTED, State.DISCONNECTING)) {
+ try {
+ final ChannelFuture future = myConnectFuture;
+ if (future != null) {
+ try {
+ beforeDisconnect();
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ final ChannelFuture closeFuture = future.getChannel().close();
+ closeFuture.awaitUninterruptibly();
+ }
+ }
+ finally {
+ myConnectFuture = null;
+ myState.compareAndSet(State.DISCONNECTING, State.DISCONNECTED);
+ try {
+ onDisconnect();
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+ }
+ }
+
+ public final boolean isConnected() {
+ return myState.get() == State.CONNECTED;
+ }
+
+ public final RequestFuture<T> sendMessage(final UUID messageId, MessageLite message, @Nullable final T responseHandler, @Nullable final RequestFuture.CancelAction<T> cancelAction) {
+ final RequestFuture<T> requestFuture = new RequestFuture<T>(responseHandler, messageId, cancelAction);
+ myMessageHandler.registerFuture(messageId, requestFuture);
+ final ChannelFuture connectFuture = myConnectFuture;
+ final Channel channel = connectFuture != null? connectFuture.getChannel() : null;
+ if (channel != null && channel.isConnected()) {
+ Channels.write(channel, message).addListener(new ChannelFutureListener() {
+ public void operationComplete(ChannelFuture future) throws Exception {
+ if (!future.isSuccess()) {
+ notifyTerminated(messageId, requestFuture, responseHandler);
+ }
+ }
+ });
+ }
+ else {
+ notifyTerminated(messageId, requestFuture, responseHandler);
+ }
+ return requestFuture;
+ }
+
+ private void notifyTerminated(UUID messageId, RequestFuture<T> requestFuture, @Nullable T responseHandler) {
+ try {
+ myMessageHandler.removeFuture(messageId);
+ if (responseHandler != null) {
+ responseHandler.sessionTerminated();
+ }
+ }
+ finally {
+ requestFuture.setDone();
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java b/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java
new file mode 100644
index 000000000000..675a6296f0a7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.client;
+
+import org.jboss.netty.channel.MessageEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/22/12
+*/
+public interface UUIDGetter {
+ @NotNull UUID getSessionUUID(@NotNull MessageEvent e);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
new file mode 100644
index 000000000000..56985a2f8c11
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import org.apache.log4j.Level;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.*;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.CmdlineProtoUtil;
+import org.jetbrains.jps.api.CmdlineRemoteProto;
+import org.jetbrains.jps.incremental.Utils;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.util.UUID;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 4/16/12
+ */
+public class BuildMain {
+ public static final Key<String> FORCE_MODEL_LOADING_PARAMETER = Key.create("_force_model_loading");
+ private static final String LOG_FILE_NAME = "log.xml";
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildMain");
+ private static NioClientSocketChannelFactory ourChannelFactory;
+
+ public static void main(String[] args){
+ System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path"));
+ final String host = args[0];
+ final int port = Integer.parseInt(args[1]);
+ final UUID sessionId = UUID.fromString(args[2]);
+ final File systemDir = new File(FileUtil.toCanonicalPath(args[3]));
+ Utils.setSystemRoot(systemDir);
+
+ initLoggers();
+
+ ourChannelFactory = new NioClientSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
+ final ClientBootstrap bootstrap = new ClientBootstrap(ourChannelFactory);
+ bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
+ public ChannelPipeline getPipeline() throws Exception {
+ return Channels.pipeline(
+ new ProtobufVarint32FrameDecoder(),
+ new ProtobufDecoder(CmdlineRemoteProto.Message.getDefaultInstance()),
+ new ProtobufVarint32LengthFieldPrepender(),
+ new ProtobufEncoder(),
+ new MyMessageHandler(sessionId)
+ );
+ }
+ });
+ bootstrap.setOption("tcpNoDelay", true);
+ bootstrap.setOption("keepAlive", true);
+
+ final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
+ future.awaitUninterruptibly();
+
+ final boolean success = future.isSuccess();
+
+ if (success) {
+ Channels.write(future.getChannel(), CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest()));
+ }
+ else {
+ final Throwable reason = future.getCause();
+ System.err.println("Error connecting to " + host + ":" + port + "; reason: " + (reason != null? reason.getMessage() : "unknown"));
+ if (reason != null) {
+ reason.printStackTrace(System.err);
+ }
+ System.err.println("Exiting.");
+ System.exit(-1);
+ }
+ }
+
+ private static class MyMessageHandler extends SimpleChannelHandler {
+ private final UUID mySessionId;
+ private volatile BuildSession mySession;
+
+ private MyMessageHandler(UUID sessionId) {
+ mySessionId = sessionId;
+ }
+
+ @Override
+ public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ CmdlineRemoteProto.Message message = (CmdlineRemoteProto.Message)e.getMessage();
+ final CmdlineRemoteProto.Message.Type type = message.getType();
+ final Channel channel = ctx.getChannel();
+
+ if (type == CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE) {
+ final CmdlineRemoteProto.Message.ControllerMessage controllerMessage = message.getControllerMessage();
+ switch (controllerMessage.getType()) {
+
+ case BUILD_PARAMETERS: {
+ if (mySession == null) {
+ final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null;
+ final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta);
+ mySession = session;
+ SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
+ public void run() {
+ try {
+ session.run();
+ }
+ finally {
+ channel.close();
+ System.exit(0);
+ }
+ }
+ });
+ }
+ else {
+ LOG.info("Cannot start another build session because one is already running");
+ }
+ return;
+ }
+
+ case FS_EVENT: {
+ final BuildSession session = mySession;
+ if (session != null) {
+ session.processFSEvent(controllerMessage.getFsEvent());
+ }
+ return;
+ }
+
+ case CONSTANT_SEARCH_RESULT: {
+ final BuildSession session = mySession;
+ if (session != null) {
+ session.processConstantSearchResult(controllerMessage.getConstantSearchResult());
+ }
+ return;
+ }
+
+ case CANCEL_BUILD_COMMAND: {
+ final BuildSession session = mySession;
+ if (session != null) {
+ session.cancel();
+ }
+ else {
+ LOG.info("Cannot cancel build: no build session is running");
+ channel.close();
+ }
+ return;
+ }
+ }
+ }
+
+ Channels.write(channel, CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure("Unsupported message type: " + type.name(), null)));
+ }
+
+ @Override
+ public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ try {
+ super.channelClosed(ctx, e);
+ }
+ finally {
+ new Thread("Shutdown thread") {
+ public void run() {
+ try {
+ ourChannelFactory.releaseExternalResources();
+ }
+ finally {
+ System.exit(0);
+ }
+ }
+ }.start();
+ }
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ try {
+ super.channelDisconnected(ctx, e);
+ }
+ finally {
+ ctx.getChannel().close();
+ }
+ }
+ }
+
+ private static void initLoggers() {
+ if (new File(LOG_FILE_NAME).exists()) {
+ DOMConfigurator.configure(LOG_FILE_NAME);
+ }
+
+ Logger.setFactory(new Logger.Factory() {
+ @Override
+ public Logger getLoggerInstance(String category) {
+ final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
+
+ return new Logger() {
+ @Override
+ public boolean isDebugEnabled() {
+ return logger.isDebugEnabled();
+ }
+
+ @Override
+ public void debug(@NonNls String message) {
+ logger.debug(message);
+ }
+
+ @Override
+ public void debug(@Nullable Throwable t) {
+ logger.debug("", t);
+ }
+
+ @Override
+ public void debug(@NonNls String message, @Nullable Throwable t) {
+ logger.debug(message, t);
+ }
+
+ @Override
+ public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
+ logger.error(message, t);
+ }
+
+ @Override
+ public void info(@NonNls String message) {
+ logger.info(message);
+ }
+
+ @Override
+ public void info(@NonNls String message, @Nullable Throwable t) {
+ logger.info(message, t);
+ }
+
+ @Override
+ public void warn(@NonNls String message, @Nullable Throwable t) {
+ logger.warn(message, t);
+ }
+
+ @Override
+ public void setLevel(Level level) {
+ logger.setLevel(level);
+ }
+ };
+ }
+ });
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java
new file mode 100644
index 000000000000..0fd522e6053b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.BuildType;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.api.GlobalOptions;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.impl.BuildDataPathsImpl;
+import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
+import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
+import org.jetbrains.jps.incremental.storage.BuildTargetsState;
+import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.indices.impl.IgnoredFileIndexImpl;
+import org.jetbrains.jps.indices.impl.ModuleExcludeIndexImpl;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
+
+/**
+ * @author nik
+ */
+public class BuildRunner {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildRunner");
+ public static final boolean PARALLEL_BUILD_ENABLED = Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false"));
+ private static final boolean STORE_TEMP_CACHES_IN_MEMORY = PARALLEL_BUILD_ENABLED || System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null;
+ private final JpsModelLoader myModelLoader;
+ private final List<TargetTypeBuildScope> myScopes;
+ private final List<String> myFilePaths;
+ private final Map<String, String> myBuilderParams;
+ private boolean myForceCleanCaches;
+
+ public BuildRunner(JpsModelLoader modelLoader, List<TargetTypeBuildScope> scopes, List<String> filePaths, Map<String, String> builderParams) {
+ myModelLoader = modelLoader;
+ myScopes = scopes;
+ myFilePaths = filePaths;
+ myBuilderParams = builderParams;
+ }
+
+ public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException {
+ final JpsModel jpsModel = myModelLoader.loadModel();
+ BuildDataPaths dataPaths = new BuildDataPathsImpl(dataStorageRoot);
+ BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(jpsModel);
+ ModuleExcludeIndex index = new ModuleExcludeIndexImpl(jpsModel);
+ IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(jpsModel);
+ BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, jpsModel, index, dataPaths, ignoredFileIndex);
+ BuildTargetsState targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex);
+
+ ProjectTimestamps projectTimestamps = null;
+ BuildDataManager dataManager = null;
+ try {
+ projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState);
+ dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
+ if (dataManager.versionDiffers()) {
+ myForceCleanCaches = true;
+ msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Dependency data format has changed, project rebuild required"));
+ }
+ }
+ catch (Exception e) {
+ // second try
+ LOG.info(e);
+ if (projectTimestamps != null) {
+ projectTimestamps.close();
+ }
+ if (dataManager != null) {
+ dataManager.close();
+ }
+ myForceCleanCaches = true;
+ FileUtil.delete(dataStorageRoot);
+ targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex);
+ projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState);
+ dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
+ // second attempt succeded
+ msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Project rebuild forced: " + e.getMessage()));
+ }
+
+ return new ProjectDescriptor(jpsModel, fsState, projectTimestamps, dataManager, BuildLoggingManager.DEFAULT, index, targetsState,
+ targetIndex, buildRootIndex, ignoredFileIndex);
+ }
+
+ public void runBuild(ProjectDescriptor pd, CanceledStatus cs, @Nullable Callbacks.ConstantAffectionResolver constantSearch,
+ MessageHandler msgHandler, BuildType buildType) throws Exception {
+ for (int attempt = 0; attempt < 2; attempt++) {
+ if (myForceCleanCaches && myScopes.isEmpty() && myFilePaths.isEmpty()) {
+ // if compilation scope is the whole project and cache rebuild is forced, use PROJECT_REBUILD for faster compilation
+ buildType = BuildType.PROJECT_REBUILD;
+ }
+
+ final CompileScope compileScope = createCompilationScope(buildType, pd, myScopes, myFilePaths);
+ final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), myBuilderParams, cs, constantSearch);
+ builder.addMessageHandler(msgHandler);
+ try {
+ switch (buildType) {
+ case PROJECT_REBUILD:
+ builder.build(compileScope, false, true, myForceCleanCaches);
+ break;
+
+ case FORCED_COMPILATION:
+ builder.build(compileScope, false, false, myForceCleanCaches);
+ break;
+
+ case MAKE:
+ builder.build(compileScope, true, false, myForceCleanCaches);
+ break;
+
+ case CLEAN:
+ //todo[nik]
+ // new ProjectBuilder(new GantBinding(), project).clean();
+ break;
+ case UP_TO_DATE_CHECK:
+ builder.checkUpToDate(compileScope);
+ break;
+ }
+ break; // break attempts loop
+ }
+ catch (RebuildRequestedException e) {
+ if (attempt == 0) {
+ LOG.info(e);
+ myForceCleanCaches = true;
+ }
+ else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ private static CompileScope createCompilationScope(BuildType buildType, ProjectDescriptor pd, List<TargetTypeBuildScope> scopes,
+ Collection<String> paths) throws Exception {
+ Set<BuildTargetType<?>> targetTypes = new HashSet<BuildTargetType<?>>();
+ Set<BuildTarget<?>> targets = new HashSet<BuildTarget<?>>();
+ Map<BuildTarget<?>, Set<File>> files;
+
+ for (TargetTypeBuildScope scope : scopes) {
+ BuildTargetType<?> targetType = BuilderRegistry.getInstance().getTargetType(scope.getTypeId());
+ if (targetType == null) {
+ LOG.info("Unknown target type: " + scope.getTypeId());
+ continue;
+ }
+ if (scope.getAllTargets()) {
+ targetTypes.add(targetType);
+ }
+ else {
+ BuildTargetLoader<?> loader = targetType.createLoader(pd.getModel());
+ for (String targetId : scope.getTargetIdList()) {
+ BuildTarget<?> target = loader.createTarget(targetId);
+ if (target != null) {
+ targets.add(target);
+ }
+ else {
+ LOG.info("Unknown " + targetType + " target id: " + targetId);
+ }
+ }
+ }
+ }
+
+ final Timestamps timestamps = pd.timestamps.getStorage();
+ if (!paths.isEmpty()) {
+ files = new HashMap<BuildTarget<?>, Set<File>>();
+ for (String path : paths) {
+ final File file = new File(path);
+ final Collection<BuildRootDescriptor> descriptors = pd.getBuildRootIndex().findAllParentDescriptors(file, null);
+ for (BuildRootDescriptor descriptor : descriptors) {
+ Set<File> fileSet = files.get(descriptor.getTarget());
+ if (fileSet == null) {
+ fileSet = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ files.put(descriptor.getTarget(), fileSet);
+ }
+ fileSet.add(file);
+ if (buildType == BuildType.FORCED_COMPILATION) {
+ pd.fsState.markDirty(null, file, descriptor, timestamps, false);
+ }
+ }
+ }
+ }
+ else {
+ files = Collections.emptyMap();
+ }
+
+ return new CompileScopeImpl(!(buildType == BuildType.MAKE || buildType == BuildType.UP_TO_DATE_CHECK), targetTypes, targets, files);
+ }
+
+ public List<TargetTypeBuildScope> getScopes() {
+ return myScopes;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
new file mode 100644
index 000000000000..e41a788e44e0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
+import com.intellij.openapi.util.io.FileSystemUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.concurrency.SequentialTaskExecutor;
+import com.intellij.util.io.DataOutputStream;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.Channels;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.*;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.incremental.MessageHandler;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.incremental.Utils;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.fs.FSState;
+import org.jetbrains.jps.incremental.messages.*;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 4/17/12
+*/
+final class BuildSession implements Runnable, CanceledStatus {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildSession");
+ private static final String FS_STATE_FILE = "fs_state.dat";
+ private final UUID mySessionId;
+ private final Channel myChannel;
+ private volatile boolean myCanceled = false;
+ private String myProjectPath;
+ @Nullable
+ private CmdlineRemoteProto.Message.ControllerMessage.FSEvent myInitialFSDelta;
+ // state
+ private EventsProcessor myEventsProcessor = new EventsProcessor();
+ private volatile long myLastEventOrdinal;
+ private volatile ProjectDescriptor myProjectDescriptor;
+ private final Map<Pair<String, String>, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConstantSearchFuture>());
+ private final ConstantSearch myConstantSearch = new ConstantSearch();
+ private final BuildRunner myBuildRunner;
+ private final boolean myForceModelLoading;
+ private BuildType myBuildType;
+
+ BuildSession(UUID sessionId,
+ Channel channel,
+ CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage params,
+ @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta) {
+ mySessionId = sessionId;
+ myChannel = channel;
+
+ // globals
+ Map<String, String> pathVars = new HashMap<String, String>();
+ final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = params.getGlobalSettings();
+ for (CmdlineRemoteProto.Message.KeyValuePair variable : globals.getPathVariableList()) {
+ pathVars.put(variable.getKey(), variable.getValue());
+ }
+
+ // session params
+ myProjectPath = FileUtil.toCanonicalPath(params.getProjectId());
+ String globalOptionsPath = FileUtil.toCanonicalPath(globals.getGlobalOptionsPath());
+ myBuildType = convertCompileType(params.getBuildType());
+ List<TargetTypeBuildScope> scopes = params.getScopeList();
+ List<String> filePaths = params.getFilePathList();
+ Map<String, String> builderParams = new HashMap<String, String>();
+ for (CmdlineRemoteProto.Message.KeyValuePair pair : params.getBuilderParameterList()) {
+ builderParams.put(pair.getKey(), pair.getValue());
+ }
+ myInitialFSDelta = delta;
+ JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, pathVars, null);
+ myForceModelLoading = Boolean.parseBoolean(builderParams.get(BuildMain.FORCE_MODEL_LOADING_PARAMETER.toString()));
+ myBuildRunner = new BuildRunner(loader, scopes, filePaths, builderParams);
+ }
+
+ public void run() {
+ Throwable error = null;
+ final Ref<Boolean> hasErrors = new Ref<Boolean>(false);
+ final Ref<Boolean> doneSomething = new Ref<Boolean>(false);
+ try {
+ ProfilingHelper profilingHelper = null;
+ if (Utils.IS_PROFILING_MODE) {
+ profilingHelper = new ProfilingHelper();
+ profilingHelper.startProfiling();
+ }
+
+ runBuild(new MessageHandler() {
+ public void processMessage(BuildMessage buildMessage) {
+ final CmdlineRemoteProto.Message.BuilderMessage response;
+ if (buildMessage instanceof FileGeneratedEvent) {
+ final Collection<Pair<String, String>> paths = ((FileGeneratedEvent)buildMessage).getPaths();
+ response = !paths.isEmpty() ? CmdlineProtoUtil.createFileGeneratedEvent(paths) : null;
+ }
+ else if (buildMessage instanceof DoneSomethingNotification) {
+ doneSomething.set(true);
+ response = null;
+ }
+ else if (buildMessage instanceof CompilerMessage) {
+ doneSomething.set(true);
+ final CompilerMessage compilerMessage = (CompilerMessage)buildMessage;
+ final String compilerName = compilerMessage.getCompilerName();
+ final String text = !StringUtil.isEmptyOrSpaces(compilerName)? compilerName + ": " + compilerMessage.getMessageText() : compilerMessage.getMessageText();
+ final BuildMessage.Kind kind = compilerMessage.getKind();
+ if (kind == BuildMessage.Kind.ERROR) {
+ hasErrors.set(true);
+ }
+ response = CmdlineProtoUtil.createCompileMessage(
+ kind, text, compilerMessage.getSourcePath(),
+ compilerMessage.getProblemBeginOffset(), compilerMessage.getProblemEndOffset(),
+ compilerMessage.getProblemLocationOffset(), compilerMessage.getLine(), compilerMessage.getColumn(),
+ -1.0f);
+ }
+ else if (buildMessage instanceof CustomBuilderMessage) {
+ CustomBuilderMessage builderMessage = (CustomBuilderMessage)buildMessage;
+ response = CmdlineProtoUtil.createCustomBuilderMessage(builderMessage.getBuilderId(), builderMessage.getMessageType(), builderMessage.getMessageText());
+ }
+ else {
+ float done = -1.0f;
+ if (buildMessage instanceof ProgressMessage) {
+ done = ((ProgressMessage)buildMessage).getDone();
+ }
+ response = CmdlineProtoUtil.createCompileProgressMessageResponse(buildMessage.getMessageText(), done);
+ }
+ if (response != null) {
+ Channels.write(myChannel, CmdlineProtoUtil.toMessage(mySessionId, response));
+ }
+ }
+ }, this);
+
+ if (profilingHelper != null) {
+ profilingHelper.stopProfiling();
+ }
+ }
+ catch (Throwable e) {
+ LOG.info(e);
+ error = e;
+ }
+ finally {
+ finishBuild(error, hasErrors.get(), doneSomething.get());
+ }
+ }
+
+ private void runBuild(final MessageHandler msgHandler, CanceledStatus cs) throws Throwable{
+ final File dataStorageRoot = Utils.getDataStorageRoot(myProjectPath);
+ if (dataStorageRoot == null) {
+ msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.ERROR, "Cannot determine build data storage root for project " + myProjectPath));
+ return;
+ }
+ if (!dataStorageRoot.exists()) {
+ // invoked the very first time for this project. Force full rebuild
+ myBuildType = BuildType.PROJECT_REBUILD;
+ }
+
+ final DataInputStream fsStateStream = createFSDataStream(dataStorageRoot);
+
+ if (fsStateStream != null) {
+ // optimization: check whether we can skip the build
+ final boolean hasWorkToDoWithModules = fsStateStream.readBoolean();
+ if (!myForceModelLoading && (myBuildType == BuildType.MAKE || myBuildType == BuildType.UP_TO_DATE_CHECK) && !hasWorkToDoWithModules && scopeContainsModulesOnly(myBuildRunner.getScopes()) && !containsChanges(myInitialFSDelta)) {
+ updateFsStateOnDisk(dataStorageRoot, fsStateStream, myInitialFSDelta.getOrdinal());
+ return;
+ }
+ }
+
+ final BuildFSState fsState = new BuildFSState(false);
+ try {
+ final ProjectDescriptor pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
+ myProjectDescriptor = pd;
+ if (fsStateStream != null) {
+ try {
+ try {
+ fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
+ applyFSEvent(pd, myInitialFSDelta, false);
+ }
+ finally {
+ fsStateStream.close();
+ }
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ fsState.clearAll();
+ }
+ }
+ myLastEventOrdinal = myInitialFSDelta != null? myInitialFSDelta.getOrdinal() : 0L;
+
+ // free memory
+ myInitialFSDelta = null;
+ // ensure events from controller are processed after FSState initialization
+ myEventsProcessor.startProcessing();
+
+ myBuildRunner.runBuild(pd, cs, myConstantSearch, msgHandler, myBuildType);
+ }
+ finally {
+ saveData(fsState, dataStorageRoot);
+ }
+ }
+
+ private static boolean scopeContainsModulesOnly(List<TargetTypeBuildScope> scopes) {
+ for (TargetTypeBuildScope scope : scopes) {
+ String typeId = scope.getTypeId();
+ if (!typeId.equals(JavaModuleBuildTargetType.PRODUCTION.getTypeId()) && !typeId.equals(JavaModuleBuildTargetType.TEST.getTypeId())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void saveData(final BuildFSState fsState, File dataStorageRoot) {
+ final boolean wasInterrupted = Thread.interrupted();
+ try {
+ saveFsState(dataStorageRoot, fsState);
+ final ProjectDescriptor pd = myProjectDescriptor;
+ if (pd != null) {
+ pd.release();
+ }
+ }
+ finally {
+ if (wasInterrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ public void processFSEvent(final CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) {
+ myEventsProcessor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ applyFSEvent(myProjectDescriptor, event, true);
+ myLastEventOrdinal += 1;
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ });
+ }
+
+ public void processConstantSearchResult(CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult result) {
+ final ConstantSearchFuture future = mySearchTasks.remove(Pair.create(result.getOwnerClassName(), result.getFieldName()));
+ if (future != null) {
+ if (result.getIsSuccess()) {
+ final List<String> paths = result.getPathList();
+ final List<File> files = new ArrayList<File>(paths.size());
+ for (String path : paths) {
+ files.add(new File(path));
+ }
+ future.setResult(files);
+ LOG.debug("Constant search result: " + files.size() + " affected files found");
+ }
+ else {
+ future.setDone();
+ LOG.debug("Constant search failed");
+ }
+ }
+ }
+
+ private void applyFSEvent(ProjectDescriptor pd, @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent event, final boolean saveEventStamp) throws IOException {
+ if (event == null) {
+ return;
+ }
+
+ final Timestamps timestamps = pd.timestamps.getStorage();
+ boolean cacheCleared = false;
+ for (String deleted : event.getDeletedPathsList()) {
+ final File file = new File(deleted);
+ Collection<BuildRootDescriptor> descriptor = pd.getBuildRootIndex().findAllParentDescriptors(file, null, null);
+ if (!descriptor.isEmpty()) {
+ if (!cacheCleared) {
+ pd.getFSCache().clear();
+ cacheCleared = true;
+ }
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Applying deleted path from fs event: " + file.getPath());
+ }
+ for (BuildRootDescriptor rootDescriptor : descriptor) {
+ pd.fsState.registerDeleted(rootDescriptor.getTarget(), file, timestamps);
+ }
+ }
+ else if (Utils.IS_TEST_MODE) {
+ LOG.info("Skipping deleted path: " + file.getPath());
+ }
+ }
+ for (String changed : event.getChangedPathsList()) {
+ final File file = new File(changed);
+ Collection<BuildRootDescriptor> descriptors = pd.getBuildRootIndex().findAllParentDescriptors(file, null, null);
+ if (!descriptors.isEmpty()) {
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Applying dirty path from fs event: " + file.getPath());
+ }
+ long fileStamp = -1L;
+ for (BuildRootDescriptor descriptor : descriptors) {
+ if (!descriptor.isGenerated()) { // ignore generates sources as they are processed at the time of generation
+ if (fileStamp == -1L) {
+ fileStamp = FileSystemUtil.lastModified(file); // lazy init
+ }
+ long stamp = timestamps.getStamp(file, descriptor.getTarget());
+ if (stamp != fileStamp) {
+ if (!cacheCleared) {
+ pd.getFSCache().clear();
+ cacheCleared = true;
+ }
+ pd.fsState.markDirty(null, file, descriptor, timestamps, saveEventStamp);
+ }
+ }
+ }
+ }
+ else if (Utils.IS_TEST_MODE) {
+ LOG.info("Skipping dirty path: " + file.getPath());
+ }
+ }
+ }
+
+ private void updateFsStateOnDisk(File dataStorageRoot, DataInputStream original, final long ordinal) {
+ final File file = new File(dataStorageRoot, FS_STATE_FILE);
+ try {
+ final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream();
+ final DataOutputStream out = new DataOutputStream(bytes);
+ try {
+ out.writeInt(FSState.VERSION);
+ out.writeLong(ordinal);
+ out.writeBoolean(false);
+ while (true) {
+ final int b = original.read();
+ if (b == -1) {
+ break;
+ }
+ out.write(b);
+ }
+ }
+ finally {
+ out.close();
+ }
+
+ saveOnDisk(bytes, file);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ FileUtil.delete(file);
+ }
+ }
+
+ private void saveFsState(File dataStorageRoot, BuildFSState state) {
+ final ProjectDescriptor pd = myProjectDescriptor;
+ final File file = new File(dataStorageRoot, FS_STATE_FILE);
+ try {
+ final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream();
+ final DataOutputStream out = new DataOutputStream(bytes);
+ try {
+ out.writeInt(FSState.VERSION);
+ out.writeLong(myLastEventOrdinal);
+ boolean hasWorkToDoWithModules = false;
+ for (JpsModule module : pd.getProject().getModules()) {
+ for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
+ if (state.hasWorkToDo(new ModuleBuildTarget(module, type))) {
+ hasWorkToDoWithModules = true;
+ break;
+ }
+ }
+ if (hasWorkToDoWithModules) {
+ break;
+ }
+ }
+ out.writeBoolean(hasWorkToDoWithModules);
+ state.save(out);
+ }
+ finally {
+ out.close();
+ }
+
+ saveOnDisk(bytes, file);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ FileUtil.delete(file);
+ }
+ }
+
+ private static void saveOnDisk(BufferExposingByteArrayOutputStream bytes, final File file) throws IOException {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ }
+ catch (FileNotFoundException e) {
+ FileUtil.createIfDoesntExist(file);
+ }
+
+ if (fos == null) {
+ fos = new FileOutputStream(file);
+ }
+ try {
+ fos.write(bytes.getInternalBuffer(), 0, bytes.size());
+ }
+ finally {
+ fos.close();
+ }
+ }
+
+ @Nullable
+ private DataInputStream createFSDataStream(File dataStorageRoot) {
+ if (myInitialFSDelta == null) {
+ // this will force FS rescan
+ return null;
+ }
+ try {
+ final File file = new File(dataStorageRoot, FS_STATE_FILE);
+ final InputStream fs = new FileInputStream(file);
+ byte[] bytes;
+ try {
+ bytes = FileUtil.loadBytes(fs, (int)file.length());
+ }
+ finally {
+ fs.close();
+ }
+ final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
+ final int version = in.readInt();
+ if (version != FSState.VERSION) {
+ return null;
+ }
+ final long savedOrdinal = in.readLong();
+ if (savedOrdinal + 1L != myInitialFSDelta.getOrdinal()) {
+ return null;
+ }
+ return in;
+ }
+ catch (FileNotFoundException ignored) {
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ return null;
+ }
+
+ private static boolean containsChanges(CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) {
+ return event.getChangedPathsCount() != 0 || event.getDeletedPathsCount() != 0;
+ }
+
+ private void finishBuild(Throwable error, boolean hadBuildErrors, boolean doneSomething) {
+ CmdlineRemoteProto.Message lastMessage = null;
+ try {
+ if (error != null) {
+ Throwable cause = error.getCause();
+ if (cause == null) {
+ cause = error;
+ }
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final PrintStream stream = new PrintStream(out);
+ try {
+ cause.printStackTrace(stream);
+ }
+ finally {
+ stream.close();
+ }
+
+ final StringBuilder messageText = new StringBuilder();
+ messageText.append("Internal error: (").append(cause.getClass().getName()).append(") ").append(cause.getMessage());
+ final String trace = out.toString();
+ if (!trace.isEmpty()) {
+ messageText.append("\n").append(trace);
+ }
+ lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure(messageText.toString(), cause));
+ }
+ else {
+ CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status status = CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.SUCCESS;
+ if (myCanceled) {
+ status = CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED;
+ }
+ else if (hadBuildErrors) {
+ status = CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.ERRORS;
+ }
+ else if (!doneSomething){
+ status = CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.UP_TO_DATE;
+ }
+ lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createBuildCompletedEvent("build completed", status));
+ }
+ }
+ catch (Throwable e) {
+ lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
+ }
+ finally {
+ try {
+ Channels.write(myChannel, lastMessage).await();
+ }
+ catch (InterruptedException e) {
+ LOG.info(e);
+ }
+ }
+ }
+
+ public void cancel() {
+ myCanceled = true;
+ }
+
+ @Override
+ public boolean isCanceled() {
+ return myCanceled;
+ }
+
+ private static BuildType convertCompileType(CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.Type compileType) {
+ switch (compileType) {
+ case CLEAN: return BuildType.CLEAN;
+ case MAKE: return BuildType.MAKE;
+ case REBUILD: return BuildType.PROJECT_REBUILD;
+ case FORCED_COMPILATION: return BuildType.FORCED_COMPILATION;
+ case UP_TO_DATE_CHECK: return BuildType.UP_TO_DATE_CHECK;
+ }
+ return BuildType.MAKE; // use make by default
+ }
+
+ private static class EventsProcessor extends SequentialTaskExecutor {
+ private final AtomicBoolean myProcessingEnabled = new AtomicBoolean(false);
+
+ EventsProcessor() {
+ super(SharedThreadPool.getInstance());
+ }
+
+ public void startProcessing() {
+ if (!myProcessingEnabled.getAndSet(true)) {
+ super.processQueue();
+ }
+ }
+
+ @Override
+ protected void processQueue() {
+ if (myProcessingEnabled.get()) {
+ super.processQueue();
+ }
+ }
+ }
+
+ private class ConstantSearch implements Callbacks.ConstantAffectionResolver {
+
+ private ConstantSearch() {
+ }
+
+ @Nullable @Override
+ public Future<Callbacks.ConstantAffection> request(String ownerClassName, String fieldName, int accessFlags, boolean fieldRemoved, boolean accessChanged) {
+ final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.Builder task =
+ CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.newBuilder();
+ task.setOwnerClassName(ownerClassName);
+ task.setFieldName(fieldName);
+ task.setAccessFlags(accessFlags);
+ task.setIsAccessChanged(accessChanged);
+ task.setIsFieldRemoved(fieldRemoved);
+ final ConstantSearchFuture future = new ConstantSearchFuture(BuildSession.this);
+ final ConstantSearchFuture prev = mySearchTasks.put(new Pair<String, String>(ownerClassName, fieldName), future);
+ if (prev != null) {
+ prev.setDone();
+ }
+ Channels.write(myChannel,
+ CmdlineProtoUtil.toMessage(
+ mySessionId, CmdlineRemoteProto.Message.BuilderMessage.newBuilder().setType(CmdlineRemoteProto.Message.BuilderMessage.Type.CONSTANT_SEARCH_TASK).setConstantSearchTask(task.build()).build()
+ )
+ );
+ return future;
+ }
+ }
+
+ private static class ConstantSearchFuture extends BasicFuture<Callbacks.ConstantAffection> {
+ private volatile Callbacks.ConstantAffection myResult = Callbacks.ConstantAffection.EMPTY;
+ private final CanceledStatus myCanceledStatus;
+
+ private ConstantSearchFuture(CanceledStatus canceledStatus) {
+ myCanceledStatus = canceledStatus;
+ }
+
+ public void setResult(final Collection<File> affectedFiles) {
+ myResult = new Callbacks.ConstantAffection(affectedFiles);
+ setDone();
+ }
+
+ @Override
+ public Callbacks.ConstantAffection get() throws InterruptedException, ExecutionException {
+ while (true) {
+ try {
+ return get(300L, TimeUnit.MILLISECONDS);
+ }
+ catch (TimeoutException ignored) {
+ }
+ if (myCanceledStatus.isCanceled()) {
+ return myResult;
+ }
+ }
+ }
+
+ @Override
+ public Callbacks.ConstantAffection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ super.get(timeout, unit);
+ return myResult;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
new file mode 100644
index 000000000000..03a527fdb2d5
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import com.google.protobuf.Message;
+import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.uiDesigner.compiler.AlienFormFileException;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.SystemProperties;
+import com.intellij.util.containers.ContainerUtil;
+import com.jgoodies.forms.layout.CellConstraints;
+import net.n3.nanoxml.IXMLBuilder;
+import org.jboss.netty.util.Version;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.jps.javac.JavacServer;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.impl.JpsModelImpl;
+import org.jetbrains.jps.model.serialization.JpsProjectLoader;
+
+import javax.tools.*;
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/12/11
+ */
+public class ClasspathBootstrap {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.ClasspathBootstrap");
+
+ private static class OptimizedFileManagerClassHolder {
+ static final String CLASS_NAME = "org.jetbrains.jps.javac.OptimizedFileManager";
+ static final Class<StandardJavaFileManager> managerClass;
+ static {
+ Class<StandardJavaFileManager> aClass;
+ try {
+ @SuppressWarnings("unchecked") Class<StandardJavaFileManager> c = (Class<StandardJavaFileManager>)Class.forName(CLASS_NAME);
+ aClass = c;
+ }
+ catch (Throwable e) {
+ aClass = null;
+ }
+ managerClass = aClass;
+ }
+
+ private OptimizedFileManagerClassHolder() {
+ }
+ }
+
+ private static class OptimizedFileManager17ClassHolder {
+ static final String CLASS_NAME = "org.jetbrains.jps.javac.OptimizedFileManager17";
+ static final Class<StandardJavaFileManager> managerClass;
+ static {
+ Class<StandardJavaFileManager> aClass;
+ try {
+ @SuppressWarnings("unchecked") Class<StandardJavaFileManager> c = (Class<StandardJavaFileManager>)Class.forName(CLASS_NAME);
+ aClass = c;
+ }
+ catch (Throwable e) {
+ aClass = null;
+ }
+ managerClass = aClass;
+ }
+
+ private OptimizedFileManager17ClassHolder() {
+ }
+ }
+
+ private ClasspathBootstrap() {
+ }
+
+ public static List<String> getBuildProcessApplicationClasspath() {
+ final Set<String> cp = ContainerUtil.newHashSet();
+
+ cp.add(getResourcePath(BuildMain.class));
+
+ cp.addAll(PathManager.getUtilClassPath()); // util
+ cp.add(getResourcePath(Message.class)); // protobuf
+ cp.add(getResourcePath(Version.class)); // netty
+ cp.add(getResourcePath(ClassWriter.class)); // asm
+ cp.add(getResourcePath(ClassVisitor.class)); // asm-commons
+ cp.add(getResourcePath(JpsModel.class)); // jps-model-api
+ cp.add(getResourcePath(JpsModelImpl.class)); // jps-model-impl
+ cp.add(getResourcePath(JpsProjectLoader.class)); // jps-model-serialization
+ cp.add(getResourcePath(AlienFormFileException.class)); // forms-compiler
+ cp.add(getResourcePath(GridConstraints.class)); // forms-rt
+ cp.add(getResourcePath(CellConstraints.class)); // jGoodies-forms
+ cp.add(getResourcePath(NotNullVerifyingInstrumenter.class)); // not-null
+ cp.add(getResourcePath(IXMLBuilder.class)); // nano-xml
+
+ final Class<StandardJavaFileManager> optimizedFileManagerClass = getOptimizedFileManagerClass();
+ if (optimizedFileManagerClass != null) {
+ cp.add(getResourcePath(optimizedFileManagerClass)); // optimizedFileManager
+ }
+
+ try {
+ final Class<?> cmdLineWrapper = Class.forName("com.intellij.rt.execution.CommandLineWrapper");
+ cp.add(getResourcePath(cmdLineWrapper)); // idea_rt.jar
+ }
+ catch (Throwable ignored) {
+ }
+
+ for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler
+ final String compilerResource = getResourcePath(javaCompiler.getClass());
+ final String name = PathUtilRt.getFileName(compilerResource);
+ if (name.startsWith("ecj-") && name.endsWith(".jar")) {
+ cp.add(compilerResource);
+ }
+ }
+
+ return ContainerUtil.newArrayList(cp);
+ }
+
+ public static List<File> getJavacServerClasspath(String sdkHome) {
+ final Set<File> cp = new LinkedHashSet<File>();
+ cp.add(getResourceFile(JavacServer.class)); // self
+ // util
+ for (String path : PathManager.getUtilClassPath()) {
+ cp.add(new File(path));
+ }
+ cp.add(getResourceFile(JpsModel.class)); // jps-model-api
+ cp.add(getResourceFile(JpsModelImpl.class)); // jps-model-impl
+ cp.add(getResourceFile(Message.class)); // protobuf
+ cp.add(getResourceFile(Version.class)); // netty
+
+ final Class<StandardJavaFileManager> optimizedFileManagerClass = getOptimizedFileManagerClass();
+ if (optimizedFileManagerClass != null) {
+ cp.add(getResourceFile(optimizedFileManagerClass)); // optimizedFileManager, if applicable
+ }
+
+ try {
+ final Class<?> cmdLineWrapper = Class.forName("com.intellij.rt.execution.CommandLineWrapper");
+ cp.add(getResourceFile(cmdLineWrapper)); // idea_rt.jar
+ }
+ catch (Throwable th) {
+ LOG.info(th);
+ }
+
+ final JavaCompiler systemCompiler = ToolProvider.getSystemJavaCompiler();
+ if (systemCompiler != null) {
+ try {
+ final String localJarPath = FileUtil.toSystemIndependentName(getResourceFile(systemCompiler.getClass()).getPath());
+ final String localJavaHome = FileUtil.toSystemIndependentName(SystemProperties.getJavaHome());
+ if (FileUtil.pathsEqual(localJavaHome, FileUtil.toSystemIndependentName(sdkHome))) {
+ cp.add(new File(localJarPath));
+ }
+ else {
+ // sdkHome is not the same as the sdk used to run this process
+ final File candidate = new File(sdkHome, "lib/tools.jar");
+ if (candidate.exists()) {
+ cp.add(candidate);
+ }
+ else {
+ // last resort
+ String relPath = FileUtil.getRelativePath(localJavaHome, localJarPath, '/');
+ if (relPath != null) {
+ if (relPath.contains("..")) {
+ relPath = FileUtil.getRelativePath(FileUtil.toSystemIndependentName(new File(localJavaHome).getParent()), localJarPath, '/');
+ }
+ if (relPath != null) {
+ final File targetFile = new File(sdkHome, relPath);
+ cp.add(targetFile); // tools.jar
+ }
+ }
+ }
+ }
+ }
+ catch (Throwable th) {
+ LOG.info(th);
+ }
+ }
+
+ return new ArrayList<File>(cp);
+ }
+
+ @Nullable
+ public static Class<StandardJavaFileManager> getOptimizedFileManagerClass() {
+ final Class<StandardJavaFileManager> aClass = OptimizedFileManagerClassHolder.managerClass;
+ if (aClass != null) {
+ return aClass;
+ }
+ return OptimizedFileManager17ClassHolder.managerClass;
+ }
+
+ public static String getResourcePath(Class aClass) {
+ return PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
+ }
+
+ public static File getResourceFile(Class aClass) {
+ return new File(getResourcePath(aClass));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoader.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoader.java
new file mode 100644
index 000000000000..a5499a4c8aae
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoader.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public interface JpsModelLoader {
+ JpsModel loadModel();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoaderImpl.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoaderImpl.java
new file mode 100644
index 000000000000..0e84370d422c
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/JpsModelLoaderImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.ParameterizedRunnable;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
+import org.jetbrains.jps.model.serialization.JpsProjectLoader;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsModelLoaderImpl implements JpsModelLoader {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.JpsModelLoaderImpl");
+ private final String myProjectPath;
+ private final String myGlobalOptionsPath;
+ private final Map<String, String> myPathVars;
+ private final ParameterizedRunnable<JpsModel> myModelInitializer;
+
+ public JpsModelLoaderImpl(String projectPath, String globalOptionsPath, Map<String, String> pathVars,
+ ParameterizedRunnable<JpsModel> initializer) {
+ myProjectPath = projectPath;
+ myGlobalOptionsPath = globalOptionsPath;
+ myPathVars = pathVars;
+ myModelInitializer = initializer;
+ }
+
+ @Override
+ public JpsModel loadModel() {
+ final long start = System.currentTimeMillis();
+ try {
+ final JpsModel model = JpsElementFactory.getInstance().createModel();
+ try {
+ if (myGlobalOptionsPath != null) {
+ JpsGlobalLoader.loadGlobalSettings(model.getGlobal(), myPathVars, myGlobalOptionsPath);
+ }
+ JpsProjectLoader.loadProject(model.getProject(), myPathVars, myProjectPath);
+ if (myModelInitializer != null) {
+ myModelInitializer.run(model);
+ }
+ LOG.info("New JPS model: " + model.getProject().getModules().size() + " modules, " + model.getProject().getLibraryCollection().getLibraries().size() + " libraries");
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ return model;
+ }
+ finally {
+ final long loadTime = System.currentTimeMillis() - start;
+ LOG.info("New JPS model: project " + myProjectPath + " loaded in " + loadTime + " ms");
+ }
+ }
+
+ private static boolean isDirectoryBased(File projectFile) {
+ return !(projectFile.isFile() && projectFile.getName().endsWith(".ipr"));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProfilingHelper.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProfilingHelper.java
new file mode 100644
index 000000000000..7b584186aa56
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProfilingHelper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 12/6/12
+ */
+class ProfilingHelper {
+
+ private final Class<?> myControllerClass;
+ private final Object myController;
+
+ ProfilingHelper() throws Exception {
+ myControllerClass = Class.forName("com.yourkit.api.Controller");
+ myController = myControllerClass.newInstance();
+ }
+
+ public void startProfiling() {
+ try {
+ final Method startMethod = myControllerClass.getDeclaredMethod("startCPUProfiling", long.class, String.class);
+ if (startMethod != null) {
+ startMethod.invoke(myController, 4L/*ProfilingModes.CPU_SAMPLING*/, null);
+ }
+ else {
+ System.err.println("Cannot find method 'startCPUProfiling' in class " + myControllerClass.getName());
+ }
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stopProfiling() {
+ try {
+ final Method captureMethod = myControllerClass.getDeclaredMethod("captureSnapshot", long.class);
+ if (captureMethod != null) {
+ final String path = (String)captureMethod.invoke(myController, 0L/*ProfilingModes.SNAPSHOT_WITHOUT_HEAP*/);
+ System.err.println("CPU Snapshot captured: " + path);
+ final Method stopMethod = myControllerClass.getDeclaredMethod("stopCPUProfiling");
+ if (stopMethod != null) {
+ stopMethod.invoke(myController);
+ }
+ else {
+ System.err.println("Cannot find method 'stopCPUProfiling' in class " + myControllerClass.getName());
+ }
+ }
+ else {
+ System.err.println("Cannot find method 'captureSnapshot' in class " + myControllerClass.getName());
+ }
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java
new file mode 100644
index 000000000000..5a71526303c2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.cmdline;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTargetIndex;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.incremental.CompilerEncodingConfiguration;
+import org.jetbrains.jps.incremental.FSCache;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
+import org.jetbrains.jps.incremental.storage.BuildTargetsState;
+import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/8/12
+*/
+public final class ProjectDescriptor {
+ private final JpsProject myProject;
+ private final JpsModel myModel;
+ public final BuildFSState fsState;
+ public final ProjectTimestamps timestamps;
+ public final BuildDataManager dataManager;
+ private final BuildLoggingManager myLoggingManager;
+ private final BuildTargetsState myTargetsState;
+ private final ModuleExcludeIndex myModuleExcludeIndex;
+ private int myUseCounter = 1;
+ private Set<JpsSdk<?>> myProjectJavaSdks;
+ private CompilerEncodingConfiguration myEncodingConfiguration;
+ private final BuildRootIndex myBuildRootIndex;
+ private final BuildTargetIndex myBuildTargetIndex;
+ private final IgnoredFileIndex myIgnoredFileIndex;
+ private FSCache myFSCache = FSCache.NO_CACHE;
+
+ public ProjectDescriptor(JpsModel model,
+ BuildFSState fsState,
+ ProjectTimestamps timestamps,
+ BuildDataManager dataManager,
+ BuildLoggingManager loggingManager,
+ final ModuleExcludeIndex moduleExcludeIndex,
+ final BuildTargetsState targetsState,
+ final BuildTargetIndex buildTargetIndex, final BuildRootIndex buildRootIndex, IgnoredFileIndex ignoredFileIndex) {
+ myModel = model;
+ myIgnoredFileIndex = ignoredFileIndex;
+ myProject = model.getProject();
+ this.fsState = fsState;
+ this.timestamps = timestamps;
+ this.dataManager = dataManager;
+ myBuildTargetIndex = buildTargetIndex;
+ myBuildRootIndex = buildRootIndex;
+ myLoggingManager = loggingManager;
+ myModuleExcludeIndex = moduleExcludeIndex;
+ myProjectJavaSdks = new HashSet<JpsSdk<?>>();
+ myEncodingConfiguration = new CompilerEncodingConfiguration(model, buildRootIndex);
+ for (JpsModule module : myProject.getModules()) {
+ final JpsSdk<?> sdk = module.getSdk(JpsJavaSdkType.INSTANCE);
+ if (sdk != null && !myProjectJavaSdks.contains(sdk) && sdk.getVersionString() != null && sdk.getHomePath() != null) {
+ myProjectJavaSdks.add(sdk);
+ }
+ }
+ myTargetsState = targetsState;
+ }
+
+ @NotNull
+ public FSCache getFSCache() {
+ return myFSCache;
+ }
+
+ public void setFSCache(FSCache cache) {
+ myFSCache = cache == null? FSCache.NO_CACHE : cache;
+ }
+
+ public BuildRootIndex getBuildRootIndex() {
+ return myBuildRootIndex;
+ }
+
+ public BuildTargetIndex getBuildTargetIndex() {
+ return myBuildTargetIndex;
+ }
+
+ public IgnoredFileIndex getIgnoredFileIndex() {
+ return myIgnoredFileIndex;
+ }
+
+ public BuildTargetsState getTargetsState() {
+ return myTargetsState;
+ }
+
+ public CompilerEncodingConfiguration getEncodingConfiguration() {
+ return myEncodingConfiguration;
+ }
+
+ public Set<JpsSdk<?>> getProjectJavaSdks() {
+ return myProjectJavaSdks;
+ }
+
+ public BuildLoggingManager getLoggingManager() {
+ return myLoggingManager;
+ }
+
+ public synchronized void incUsageCounter() {
+ myUseCounter++;
+ }
+
+ public void release() {
+ boolean shouldClose;
+ synchronized (this) {
+ --myUseCounter;
+ shouldClose = myUseCounter == 0;
+ }
+ if (shouldClose) {
+ try {
+ timestamps.close();
+ }
+ finally {
+ try {
+ dataManager.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+ }
+ }
+
+ public ModuleExcludeIndex getModuleExcludeIndex() {
+ return myModuleExcludeIndex;
+ }
+
+ public JpsModel getModel() {
+ return myModel;
+ }
+
+ public JpsProject getProject() {
+ return myProject;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BinaryContent.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BinaryContent.java
new file mode 100644
index 000000000000..60c61ecd5b48
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BinaryContent.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 11/18/12
+*/
+public final class BinaryContent {
+ private final byte[] myBuffer;
+ private final int myOffset;
+ private final int myLength;
+
+ public BinaryContent(byte[] buf) {
+ this(buf, 0, buf.length);
+ }
+
+ public BinaryContent(byte[] buf, int off, int len) {
+ myBuffer = buf;
+ myOffset = off;
+ myLength = len;
+ }
+
+ public byte[] getBuffer() {
+ return myBuffer;
+ }
+
+ public int getOffset() {
+ return myOffset;
+ }
+
+ public int getLength() {
+ return myLength;
+ }
+
+ public byte[] toByteArray() {
+ return Arrays.copyOfRange(myBuffer, myOffset, myOffset + myLength);
+ }
+
+ public void saveToFile(File file) throws IOException {
+ try {
+ _writeToFile(file, this);
+ }
+ catch (IOException e) {
+ // assuming the reason is non-existing parent
+ final File parentFile = file.getParentFile();
+ if (parentFile == null) {
+ throw e;
+ }
+ if (!parentFile.mkdirs()) {
+ throw e;
+ }
+ // second attempt
+ _writeToFile(file, this);
+ }
+ }
+
+ private static void _writeToFile(final File file, BinaryContent content) throws IOException {
+ final OutputStream stream = new FileOutputStream(file);
+ try {
+ stream.write(content.getBuffer(), content.getOffset(), content.getLength());
+ }
+ finally {
+ stream.close();
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildListener.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildListener.java
new file mode 100644
index 000000000000..97d74f3122a3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.Pair;
+
+import java.util.Collection;
+import java.util.EventListener;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 5/21/12
+ */
+public interface BuildListener extends EventListener{
+
+ /**
+ * Note: when parallel build is on, might be called from several simultaneously running threads
+ * @param paths collection of pairs [output root->relative path to generated file]
+ */
+ void filesGenerated(Collection<Pair<String, String>> paths);
+
+ void filesDeleted(Collection<String> paths);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java
new file mode 100644
index 000000000000..c924d6d5e345
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.impl.BuildOutputConsumerImpl;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.messages.DoneSomethingNotification;
+import org.jetbrains.jps.incremental.messages.FileDeletedEvent;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
+import org.jetbrains.jps.incremental.storage.BuildTargetConfiguration;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/30/12
+ */
+public class BuildOperations {
+ private BuildOperations() {
+ }
+
+ public static void ensureFSStateInitialized(CompileContext context, BuildTarget<?> target) throws IOException {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final Timestamps timestamps = pd.timestamps.getStorage();
+ final BuildTargetConfiguration configuration = pd.getTargetsState().getTargetConfiguration(target);
+
+ if (context.isProjectRebuild()) {
+ FSOperations.markDirtyFiles(context, target, timestamps, true, null, null);
+ pd.fsState.markInitialScanPerformed(target);
+ configuration.save();
+ }
+ else if (context.getScope().isRecompilationForced(target) || configuration.isTargetDirty() || configuration.outputRootWasDeleted(context)) {
+ initTargetFSState(context, target, true);
+ IncProjectBuilder.clearOutputFiles(context, target);
+ pd.dataManager.cleanTargetStorages(target);
+ configuration.save();
+ }
+ else if (!pd.fsState.isInitialScanPerformed(target)) {
+ initTargetFSState(context, target, false);
+ }
+ }
+
+ private static void initTargetFSState(CompileContext context, BuildTarget<?> target, final boolean forceMarkDirty) throws IOException {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final Timestamps timestamps = pd.timestamps.getStorage();
+ final THashSet<File> currentFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ FSOperations.markDirtyFiles(context, target, timestamps, forceMarkDirty, currentFiles, null);
+
+ // handle deleted paths
+ final BuildFSState fsState = pd.fsState;
+ fsState.clearDeletedPaths(target);
+ final SourceToOutputMapping sourceToOutputMap = pd.dataManager.getSourceToOutputMap(target);
+ for (final Iterator<String> it = sourceToOutputMap.getSourcesIterator(); it.hasNext(); ) {
+ final String path = it.next();
+ // can check if the file exists
+ final File file = new File(path);
+ if (!currentFiles.contains(file)) {
+ fsState.registerDeleted(target, file, timestamps);
+ }
+ }
+ pd.fsState.markInitialScanPerformed(target);
+ }
+
+ public static <R extends BuildRootDescriptor, T extends BuildTarget<R>>
+ void buildTarget(final T target, final CompileContext context, TargetBuilder<?, ?> builder) throws ProjectBuildException, IOException {
+
+ if (builder.getTargetTypes().contains(target.getTargetType())) {
+ DirtyFilesHolder<R, T> holder = new DirtyFilesHolderBase<R, T>(context) {
+ @Override
+ public void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException {
+ context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor);
+ }
+ };
+ //noinspection unchecked
+ BuildOutputConsumerImpl outputConsumer = new BuildOutputConsumerImpl(target, context);
+ ((TargetBuilder<R, T>)builder).build(target, holder, outputConsumer, context);
+ outputConsumer.fireFileGeneratedEvent();
+ context.checkCanceled();
+ }
+ }
+
+ public static void markTargetsUpToDate(CompileContext context, BuildTargetChunk chunk) throws IOException {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final BuildFSState fsState = pd.fsState;
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ pd.getTargetsState().getTargetConfiguration(target).storeNonexistentOutputRoots(context);
+ }
+ if (!Utils.errorsDetected(context) && !context.getCancelStatus().isCanceled()) {
+ boolean marked = dropRemovedPaths(context, chunk);
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ if (context.isMake() && target instanceof ModuleBuildTarget) {
+ // ensure non-incremental flag cleared
+ context.clearNonIncrementalMark((ModuleBuildTarget)target);
+ }
+ final Timestamps timestamps = pd.timestamps.getStorage();
+ for (BuildRootDescriptor rd : pd.getBuildRootIndex().getTargetRoots(target, context)) {
+ marked |= fsState.markAllUpToDate(context, rd, timestamps);
+ }
+ }
+
+ if (marked) {
+ context.processMessage(DoneSomethingNotification.INSTANCE);
+ }
+ }
+ }
+
+ private static boolean dropRemovedPaths(CompileContext context, BuildTargetChunk chunk) throws IOException {
+ final Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(context);
+ boolean dropped = false;
+ if (map != null) {
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ final Collection<String> paths = map.remove(target);
+ if (paths != null) {
+ final SourceToOutputMapping storage = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
+ for (String path : paths) {
+ storage.remove(path);
+ dropped = true;
+ }
+ }
+ }
+ }
+ return dropped;
+ }
+
+ public static <R extends BuildRootDescriptor, T extends BuildTarget<R>>
+ Map<T, Set<File>> cleanOutputsCorrespondingToChangedFiles(final CompileContext context, DirtyFilesHolder<R, T> dirtyFilesHolder) throws ProjectBuildException {
+ final BuildDataManager dataManager = context.getProjectDescriptor().dataManager;
+ try {
+ final Map<T, Set<File>> cleanedSources = new java.util.HashMap<T, Set<File>>();
+
+ final THashSet<File> dirsToDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ final Collection<String> deletedPaths = new ArrayList<String>();
+
+ dirtyFilesHolder.processDirtyFiles(new FileProcessor<R, T>() {
+ private final Map<T, SourceToOutputMapping> mappingsCache = new java.util.HashMap<T, SourceToOutputMapping>(); // cache the mapping locally
+
+ @Override
+ public boolean apply(T target, File file, R sourceRoot) throws IOException {
+ SourceToOutputMapping srcToOut = mappingsCache.get(target);
+ if (srcToOut == null) {
+ srcToOut = dataManager.getSourceToOutputMap(target);
+ mappingsCache.put(target, srcToOut);
+ }
+ final String srcPath = file.getPath();
+ final Collection<String> outputs = srcToOut.getOutputs(srcPath);
+ if (outputs != null) {
+ final boolean shouldPruneOutputDirs = target instanceof ModuleBasedTarget;
+ for (String output : outputs) {
+ final File outFile = new File(output);
+ final boolean deleted = outFile.delete();
+ if (deleted) {
+ deletedPaths.add(output);
+ if (shouldPruneOutputDirs) {
+ final File parent = outFile.getParentFile();
+ if (parent != null) {
+ dirsToDelete.add(parent);
+ }
+ }
+ }
+ }
+ Set<File> cleaned = cleanedSources.get(target);
+ if (cleaned == null) {
+ cleaned = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ cleanedSources.put(target, cleaned);
+ }
+ cleaned.add(file);
+ }
+ return true;
+ }
+ });
+
+ if (context.isMake()) {
+ final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ logger.logDeletedFiles(deletedPaths);
+ }
+ }
+
+ if (!deletedPaths.isEmpty()) {
+ context.processMessage(new FileDeletedEvent(deletedPaths));
+ }
+ // attempting to delete potentially empty directories
+ FSOperations.pruneEmptyDirs(context, dirsToDelete);
+
+ return cleanedSources;
+ }
+ catch (Exception e) {
+ throw new ProjectBuildException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildTask.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildTask.java
new file mode 100644
index 000000000000..d0d19eabdb73
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildTask.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public abstract class BuildTask {
+ public abstract void build(CompileContext context) throws ProjectBuildException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java
new file mode 100644
index 000000000000..268d0e3bd2d8
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @see ModuleLevelBuilder
+ * @see TargetBuilder
+ *
+ * @author nik
+ */
+public abstract class Builder {
+ @NotNull
+ public abstract String getPresentableName();
+
+ public void buildStarted(CompileContext context) {
+ }
+
+ public void buildFinished(CompileContext context) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderCategory.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderCategory.java
new file mode 100644
index 000000000000..da5473ea80b3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderCategory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public enum BuilderCategory {
+ INITIAL,
+ SOURCE_GENERATOR,
+ SOURCE_INSTRUMENTER,
+ SOURCE_PROCESSOR,
+ TRANSLATOR,
+ OVERWRITING_TRANSLATOR,
+ CLASS_INSTRUMENTER,
+ CLASS_POST_PROCESSOR,
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
new file mode 100644
index 000000000000..218a1013bcf2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.diagnostic.Logger;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public class BuilderRegistry {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.BuilderRegistry");
+ private static class Holder {
+ static final BuilderRegistry ourInstance = new BuilderRegistry();
+ }
+ private final Map<BuilderCategory, List<ModuleLevelBuilder>> myModuleLevelBuilders = new HashMap<BuilderCategory, List<ModuleLevelBuilder>>();
+ private final List<TargetBuilder<?,?>> myTargetBuilders = new ArrayList<TargetBuilder<?,?>>();
+ private final Map<String, BuildTargetType<?>> myTargetTypes = new LinkedHashMap<String, BuildTargetType<?>>();
+
+ public static BuilderRegistry getInstance() {
+ return Holder.ourInstance;
+ }
+
+ private BuilderRegistry() {
+ for (BuilderCategory category : BuilderCategory.values()) {
+ myModuleLevelBuilders.put(category, new ArrayList<ModuleLevelBuilder>());
+ }
+
+ for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) {
+ myTargetBuilders.addAll(service.createBuilders());
+ final List<? extends ModuleLevelBuilder> moduleLevelBuilders = service.createModuleLevelBuilders();
+ for (ModuleLevelBuilder builder : moduleLevelBuilders) {
+ myModuleLevelBuilders.get(builder.getCategory()).add(builder);
+ }
+ for (BuildTargetType<?> type : service.getTargetTypes()) {
+ String id = type.getTypeId();
+ BuildTargetType<?> old = myTargetTypes.put(id, type);
+ if (old != null) {
+ LOG.error("Two build target types (" + type + ", " + old + ") use same id (" + id + ")");
+ }
+ }
+ }
+ }
+
+ @Nullable
+ public BuildTargetType<?> getTargetType(String typeId) {
+ return myTargetTypes.get(typeId);
+ }
+
+ public Collection<BuildTargetType<?>> getTargetTypes() {
+ return myTargetTypes.values();
+ }
+
+ public int getModuleLevelBuilderCount() {
+ int count = 0;
+ for (BuilderCategory category : BuilderCategory.values()) {
+ count += getBuilders(category).size();
+ }
+ return count;
+ }
+
+ public List<BuildTask> getBeforeTasks(){
+ return Collections.emptyList(); // todo
+ }
+
+ public List<BuildTask> getAfterTasks(){
+ return Collections.emptyList(); // todo
+ }
+
+ public List<ModuleLevelBuilder> getBuilders(BuilderCategory category){
+ return Collections.unmodifiableList(myModuleLevelBuilders.get(category));
+ }
+
+ public List<ModuleLevelBuilder> getModuleLevelBuilders() {
+ List<ModuleLevelBuilder> result = new ArrayList<ModuleLevelBuilder>();
+ for (BuilderCategory category : BuilderCategory.values()) {
+ result.addAll(getBuilders(category));
+ }
+ return result;
+ }
+
+ public List<TargetBuilder<?,?>> getTargetBuilders() {
+ return myTargetBuilders;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java
new file mode 100644
index 000000000000..ad091a0cb8fc
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class BuilderService {
+ public List<? extends BuildTargetType<?>> getTargetTypes() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends TargetBuilder<?,?>> createBuilders() {
+ return Collections.emptyList();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ChunkBuildOutputConsumerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ChunkBuildOutputConsumerImpl.java
new file mode 100644
index 000000000000..eba9148fb7d0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ChunkBuildOutputConsumerImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.impl.BuildOutputConsumerImpl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 11/16/12
+*/
+class ChunkBuildOutputConsumerImpl implements ModuleLevelBuilder.OutputConsumer {
+ private final CompileContext myContext;
+ private Map<BuildTarget<?>, BuildOutputConsumerImpl> myTarget2Consumer = new THashMap<BuildTarget<?>, BuildOutputConsumerImpl>();
+ private Map<String, CompiledClass> myClasses = new THashMap<String, CompiledClass>();
+ private Map<BuildTarget<?>, Collection<CompiledClass>> myTargetToClassesMap = new THashMap<BuildTarget<?>, Collection<CompiledClass>>();
+
+ public ChunkBuildOutputConsumerImpl(CompileContext context) {
+ myContext = context;
+ }
+
+ @Override
+ public Collection<CompiledClass> getTargetCompiledClasses(BuildTarget<?> target) {
+ final Collection<CompiledClass> classes = myTargetToClassesMap.get(target);
+ if (classes != null) {
+ return Collections.unmodifiableCollection(classes);
+ }
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ @Override
+ public Map<String, CompiledClass> getCompiledClasses() {
+ return Collections.unmodifiableMap(myClasses);
+ }
+
+ @Override
+ @Nullable
+ public BinaryContent lookupClassBytes(String className) {
+ final CompiledClass object = myClasses.get(className);
+ return object != null ? object.getContent() : null;
+ }
+
+ @Override
+ public void registerCompiledClass(BuildTarget<?> target, CompiledClass compiled) throws IOException {
+ if (compiled.getClassName() != null) {
+ myClasses.put(compiled.getClassName(), compiled);
+ Collection<CompiledClass> classes = myTargetToClassesMap.get(target);
+ if (classes == null) {
+ classes = new ArrayList<CompiledClass>();
+ myTargetToClassesMap.put(target, classes);
+ }
+ classes.add(compiled);
+ }
+ registerOutputFile(target, compiled.getOutputFile(), Collections.<String>singleton(compiled.getSourceFile().getPath()));
+ }
+
+ @Override
+ public void registerOutputFile(BuildTarget<?> target, File outputFile, Collection<String> sourcePaths) throws IOException {
+ BuildOutputConsumerImpl consumer = myTarget2Consumer.get(target);
+ if (consumer == null) {
+ consumer = new BuildOutputConsumerImpl(target, myContext);
+ myTarget2Consumer.put(target, consumer);
+ }
+ consumer.registerOutputFile(outputFile, sourcePaths);
+ }
+
+ public void fireFileGeneratedEvents() {
+ for (BuildOutputConsumerImpl consumer : myTarget2Consumer.values()) {
+ consumer.fireFileGeneratedEvent();
+ }
+ }
+
+ public void clear() {
+ myTarget2Consumer.clear();
+ myClasses.clear();
+ myTargetToClassesMap.clear();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java
new file mode 100644
index 000000000000..b878c75b3180
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.UserDataHolder;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 7/8/12
+ */
+public interface CompileContext extends UserDataHolder, MessageHandler {
+ ProjectDescriptor getProjectDescriptor();
+
+ CompileScope getScope();
+
+ boolean isMake();
+
+ boolean isProjectRebuild();
+
+ @Nullable
+ String getBuilderParameter(String paramName);
+
+ void addBuildListener(BuildListener listener);
+
+ void removeBuildListener(BuildListener listener);
+
+ boolean shouldDifferentiate(ModuleChunk chunk);
+
+ CanceledStatus getCancelStatus();
+
+ void checkCanceled() throws ProjectBuildException;
+
+ BuildLoggingManager getLoggingManager();
+
+ void setDone(float done);
+
+ long getCompilationStartStamp();
+
+ void updateCompilationStartStamp();
+
+ void markNonIncremental(ModuleBuildTarget target);
+
+ void clearNonIncrementalMark(ModuleBuildTarget target);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java
new file mode 100644
index 000000000000..5ccf72e73312
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.util.EventDispatcher;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.FileDeletedEvent;
+import org.jetbrains.jps.incremental.messages.FileGeneratedEvent;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public class CompileContextImpl extends UserDataHolderBase implements CompileContext {
+ private static final String CANCELED_MESSAGE = "The build has been canceled";
+ private final CompileScope myScope;
+ private final boolean myIsMake;
+ private final boolean myIsProjectRebuild;
+ private final MessageHandler myDelegateMessageHandler;
+ private final Set<ModuleBuildTarget> myNonIncrementalModules = new HashSet<ModuleBuildTarget>();
+
+ private volatile long myCompilationStartStamp;
+ private final ProjectDescriptor myProjectDescriptor;
+ private final Map<String, String> myBuilderParams;
+ private final CanceledStatus myCancelStatus;
+ private volatile float myDone = -1.0f;
+ private EventDispatcher<BuildListener> myListeners = EventDispatcher.create(BuildListener.class);
+
+ public CompileContextImpl(CompileScope scope,
+ ProjectDescriptor pd, boolean isMake,
+ boolean isProjectRebuild,
+ MessageHandler delegateMessageHandler,
+ Map<String, String> builderParams,
+ CanceledStatus cancelStatus) throws ProjectBuildException {
+ myProjectDescriptor = pd;
+ myBuilderParams = Collections.unmodifiableMap(builderParams);
+ myCancelStatus = cancelStatus;
+ myCompilationStartStamp = System.currentTimeMillis();
+ myScope = scope;
+ myIsProjectRebuild = isProjectRebuild;
+ myIsMake = !isProjectRebuild && isMake;
+ myDelegateMessageHandler = delegateMessageHandler;
+ }
+
+ @Override
+ public long getCompilationStartStamp() {
+ return myCompilationStartStamp;
+ }
+
+ @Override
+ public void updateCompilationStartStamp() {
+ myCompilationStartStamp = System.currentTimeMillis();
+ }
+
+ @Override
+ public boolean isMake() {
+ return myIsMake;
+ }
+
+ @Override
+ public boolean isProjectRebuild() {
+ return myIsProjectRebuild;
+ }
+
+ @Override
+ public BuildLoggingManager getLoggingManager() {
+ return myProjectDescriptor.getLoggingManager();
+ }
+
+ @Override
+ @Nullable
+ public String getBuilderParameter(String paramName) {
+ return myBuilderParams.get(paramName);
+ }
+
+ @Override
+ public void addBuildListener(BuildListener listener) {
+ myListeners.addListener(listener);
+ }
+
+ @Override
+ public void removeBuildListener(BuildListener listener) {
+ myListeners.removeListener(listener);
+ }
+
+ @Override
+ public void markNonIncremental(ModuleBuildTarget target) {
+ if (!target.isTests()) {
+ myNonIncrementalModules.add(new ModuleBuildTarget(target.getModule(), JavaModuleBuildTargetType.TEST));
+ }
+ myNonIncrementalModules.add(target);
+ }
+
+ @Override
+ public boolean shouldDifferentiate(ModuleChunk chunk) {
+ if (!isMake()) {
+ // the check makes sense only in make mode
+ return true;
+ }
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ if (myNonIncrementalModules.contains(target)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final CanceledStatus getCancelStatus() {
+ return myCancelStatus;
+ }
+
+ @Override
+ public final void checkCanceled() throws ProjectBuildException {
+ if (getCancelStatus().isCanceled()) {
+ throw new ProjectBuildException(CANCELED_MESSAGE);
+ }
+ }
+
+ @Override
+ public void clearNonIncrementalMark(ModuleBuildTarget target) {
+ myNonIncrementalModules.remove(target);
+ }
+
+ @Override
+ public CompileScope getScope() {
+ return myScope;
+ }
+
+ public void processMessage(BuildMessage msg) {
+ if (msg.getKind() == BuildMessage.Kind.ERROR) {
+ Utils.ERRORS_DETECTED_KEY.set(this, Boolean.TRUE);
+ }
+ if (msg instanceof ProgressMessage) {
+ ((ProgressMessage)msg).setDone(myDone);
+ }
+ myDelegateMessageHandler.processMessage(msg);
+ if (msg instanceof FileGeneratedEvent) {
+ final Collection<Pair<String, String>> paths = ((FileGeneratedEvent)msg).getPaths();
+ if (!paths.isEmpty()) {
+ myListeners.getMulticaster().filesGenerated(paths);
+ }
+ }
+ else if (msg instanceof FileDeletedEvent) {
+ Collection<String> paths = ((FileDeletedEvent)msg).getFilePaths();
+ myListeners.getMulticaster().filesDeleted(paths);
+ }
+ }
+
+ @Override
+ public void setDone(float done) {
+ myDone = done;
+ }
+
+ @Override
+ public ProjectDescriptor getProjectDescriptor() {
+ return myProjectDescriptor;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java
new file mode 100644
index 000000000000..c88525841237
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+
+import java.io.File;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/15/12
+ */
+public abstract class CompileScope {
+ public abstract boolean isAffected(BuildTarget<?> target, @NotNull File file);
+
+ public abstract boolean isAffected(@NotNull BuildTarget<?> target);
+
+ public abstract boolean isRecompilationForced(@NotNull BuildTarget<?> target);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java
new file mode 100644
index 000000000000..f3ecd6885712
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.ModuleBasedTarget;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class CompileScopeImpl extends CompileScope {
+ protected final boolean myForcedCompilation;
+ private final Collection<? extends BuildTargetType<?>> myTypes;
+ private final Collection<BuildTarget<?>> myTargets;
+ private final Map<BuildTarget<?>, Set<File>> myFiles;
+
+ public CompileScopeImpl(boolean forcedCompilation, Collection<? extends BuildTargetType<?>> types, Collection<BuildTarget<?>> targets,
+ Map<BuildTarget<?>, Set<File>> files) {
+ myForcedCompilation = forcedCompilation;
+ myTypes = types;
+ myTargets = targets;
+ myFiles = files;
+ }
+
+ @Override
+ public boolean isAffected(@NotNull BuildTarget<?> target) {
+ return myTypes.contains(target.getTargetType()) || myTargets.contains(target) || myFiles.containsKey(target) || isAffectedByAssociatedModule(target);
+ }
+
+ @Override
+ public boolean isRecompilationForced(@NotNull BuildTarget<?> target) {
+ return myForcedCompilation && (myTypes.contains(target.getTargetType()) || myTargets.contains(target) || isAffectedByAssociatedModule(target));
+ }
+
+ @Override
+ public boolean isAffected(BuildTarget<?> target, @NotNull File file) {
+ if (myFiles.isEmpty()) {//optimization
+ return true;
+ }
+ if (myTypes.contains(target.getTargetType()) || myTargets.contains(target) || isAffectedByAssociatedModule(target)) {
+ return true;
+ }
+ final Set<File> files = myFiles.get(target);
+ return files != null && files.contains(file);
+ }
+
+ private boolean isAffectedByAssociatedModule(BuildTarget<?> target) {
+ final JpsModule module = target instanceof ModuleBasedTarget ? ((ModuleBasedTarget)target).getModule() : null;
+ if (module != null) {
+ // this target is associated with module
+ for (JavaModuleBuildTargetType moduleType : JavaModuleBuildTargetType.ALL_TYPES) {
+ if (myTypes.contains(moduleType) || myTargets.contains(new ModuleBuildTarget(module, moduleType))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java
new file mode 100644
index 000000000000..d2e02519a1c7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/18/12
+ */
+public class CompiledClass extends UserDataHolderBase{
+ @NotNull
+ private final File myOutputFile;
+ @NotNull
+ private final File mySourceFile;
+ @Nullable
+ private final String myClassName;
+ @NotNull
+ private BinaryContent myContent;
+
+ private boolean myIsDirty = false;
+
+ public CompiledClass(@NotNull File outputFile, @NotNull File sourceFile, @Nullable String className, @NotNull BinaryContent content) {
+ myOutputFile = outputFile;
+ mySourceFile = sourceFile;
+ myClassName = className;
+ myContent = content;
+ }
+
+ public void save() throws IOException {
+ myContent.saveToFile(myOutputFile);
+ myIsDirty = false;
+ }
+
+ @NotNull
+ public File getOutputFile() {
+ return myOutputFile;
+ }
+
+ @NotNull
+ public File getSourceFile() {
+ return mySourceFile;
+ }
+
+ @Nullable
+ public String getClassName() {
+ return myClassName;
+ }
+
+ @NotNull
+ public BinaryContent getContent() {
+ return myContent;
+ }
+
+ public void setContent(@NotNull BinaryContent content) {
+ myContent = content;
+ myIsDirty = true;
+ }
+
+ public boolean isDirty() {
+ return myIsDirty;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ CompiledClass aClass = (CompiledClass)o;
+
+ if (!FileUtil.filesEqual(myOutputFile, aClass.myOutputFile)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return FileUtil.fileHashCode(myOutputFile);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java
new file mode 100644
index 000000000000..b38230e862d9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class CompilerEncodingConfiguration {
+ private final Map<String, String> myUrlToCharset;
+ private final String myProjectCharset;
+ private final BuildRootIndex myRootsIndex;
+ private Map<JpsModule, Set<String>> myModuleCharsetMap;
+
+ public CompilerEncodingConfiguration(JpsModel jpsModel, BuildRootIndex index) {
+ JpsEncodingProjectConfiguration configuration = JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(jpsModel.getProject());
+ myUrlToCharset = configuration != null ? configuration.getUrlToEncoding() : Collections.<String, String>emptyMap();
+ myProjectCharset = JpsEncodingConfigurationService.getInstance().getProjectEncoding(jpsModel);
+ myRootsIndex = index;
+ }
+
+ public Map<JpsModule, Set<String>> getModuleCharsetMap() {
+ if (myModuleCharsetMap == null) {
+ myModuleCharsetMap = computeModuleCharsetMap();
+ }
+ return myModuleCharsetMap;
+ }
+
+ private Map<JpsModule, Set<String>> computeModuleCharsetMap() {
+ final Map<JpsModule, Set<String>> map = new THashMap<JpsModule, Set<String>>();
+ final List<ModuleLevelBuilder> builders = BuilderRegistry.getInstance().getModuleLevelBuilders();
+ for (Map.Entry<String, String> entry : myUrlToCharset.entrySet()) {
+ final String fileUrl = entry.getKey();
+ final String charset = entry.getValue();
+ File file = JpsPathUtil.urlToFile(fileUrl);
+ if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builders, file))) continue;
+
+ final JavaSourceRootDescriptor rootDescriptor = myRootsIndex.findJavaRootDescriptor(null, file);
+ if (rootDescriptor == null) continue;
+
+ final JpsModule module = rootDescriptor.target.getModule();
+ Set<String> set = map.get(module);
+ if (set == null) {
+ set = new LinkedHashSet<String>();
+ map.put(module, set);
+
+ final File sourceRoot = rootDescriptor.root;
+ File current = FileUtilRt.getParentFile(file);
+ String parentCharset = null;
+ while (current != null) {
+ final String currentCharset = myUrlToCharset.get(FileUtil.toSystemIndependentName(current.getAbsolutePath()));
+ if (currentCharset != null) {
+ parentCharset = currentCharset;
+ }
+ if (FileUtil.filesEqual(current, sourceRoot)) {
+ break;
+ }
+ current = FileUtilRt.getParentFile(current);
+ }
+ if (parentCharset != null) {
+ set.add(parentCharset);
+ }
+ }
+ set.add(charset);
+ }
+
+ return map;
+ }
+
+ private static boolean shouldHonorEncodingForCompilation(List<ModuleLevelBuilder> builders, File file) {
+ for (ModuleLevelBuilder builder : builders) {
+ if (builder.shouldHonorFileEncodingForCompilation(file)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ public String getPreferredModuleChunkEncoding(@NotNull ModuleChunk moduleChunk) {
+ for (JpsModule module : moduleChunk.getModules()) {
+ final String encoding = getPreferredModuleEncoding(module);
+ if (encoding != null) {
+ return encoding;
+ }
+ }
+ return myProjectCharset;
+ }
+
+ public String getPreferredModuleEncoding(JpsModule module) {
+ final Set<String> encodings = getModuleCharsetMap().get(module);
+ return ContainerUtil.getFirstItem(encodings, null);
+ }
+
+ @NotNull
+ public Set<String> getAllModuleChunkEncodings(@NotNull ModuleChunk moduleChunk) {
+ final Map<JpsModule, Set<String>> map = getModuleCharsetMap();
+ Set<String> encodings = new HashSet<String>();
+ for (JpsModule module : moduleChunk.getModules()) {
+ final Set<String> moduleEncodings = map.get(module);
+ if (moduleEncodings != null) {
+ encodings.addAll(moduleEncodings);
+ }
+ }
+ return encodings;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ExternalProcessUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ExternalProcessUtil.java
new file mode 100644
index 000000000000..2e2991740bfa
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ExternalProcessUtil.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.cmdline.ClasspathBootstrap;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/28/11
+ */
+public class ExternalProcessUtil {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.ExternalProcessUtil");
+
+ private static class CommandLineWrapperClassHolder {
+ static final Class ourWrapperClass;
+ static {
+ Class<?> aClass = null;
+ try {
+ aClass = Class.forName("com.intellij.rt.execution.CommandLineWrapper");
+ }
+ catch (Throwable ignored) {
+ }
+ ourWrapperClass = aClass;
+ }
+ }
+
+ public static List<String> buildJavaCommandLine(String javaExecutable,
+ String mainClass,
+ List<String> bootClasspath,
+ List<String> classpath,
+ List<String> vmParams,
+ List<String> programParams) {
+ return buildJavaCommandLine(javaExecutable, mainClass, bootClasspath, classpath, vmParams, programParams, true);
+ }
+
+ public static List<String> buildJavaCommandLine(String javaExecutable,
+ String mainClass,
+ List<String> bootClasspath,
+ List<String> classpath,
+ List<String> vmParams,
+ List<String> programParams, final boolean useCommandLineWrapper) {
+ final List<String> cmdLine = new ArrayList<String>();
+
+ cmdLine.add(javaExecutable);
+
+ for (String param : vmParams) {
+ cmdLine.add(param);
+ }
+
+ if (!bootClasspath.isEmpty()) {
+ cmdLine.add("-bootclasspath");
+ cmdLine.add(StringUtil.join(bootClasspath, File.pathSeparator));
+ }
+
+ if (!classpath.isEmpty()) {
+ List<String> commandLineWrapperArgs = null;
+ if (useCommandLineWrapper) {
+ final Class wrapperClass = getCommandLineWrapperClass();
+ if (wrapperClass != null) {
+ try {
+ File classpathFile = FileUtil.createTempFile("classpath", null);
+ final PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(classpathFile)));
+ try {
+ for (String path : classpath) {
+ writer.println(path);
+ }
+ }
+ finally {
+ writer.close();
+ }
+ commandLineWrapperArgs = Arrays.asList(
+ "-classpath",
+ ClasspathBootstrap.getResourcePath(wrapperClass),
+ wrapperClass.getName(),
+ classpathFile.getAbsolutePath()
+ );
+ }
+ catch (IOException ex) {
+ LOG.info("Error starting " + mainClass + "; Classpath wrapper will not be used: ", ex);
+ }
+ }
+ else {
+ LOG.info("CommandLineWrapper class not found, classpath wrapper will not be used");
+ }
+ }
+
+ // classpath
+ if (commandLineWrapperArgs != null) {
+ cmdLine.addAll(commandLineWrapperArgs);
+ }
+ else {
+ cmdLine.add("-classpath");
+ cmdLine.add(StringUtil.join(classpath, File.pathSeparator));
+ }
+ }
+
+ // main class and params
+ cmdLine.add(mainClass);
+
+ for (String param : programParams) {
+ cmdLine.add(param);
+ }
+
+ return cmdLine;
+ }
+
+ @Nullable
+ private static Class getCommandLineWrapperClass() {
+ return CommandLineWrapperClassHolder.ourWrapperClass;
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSCache.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSCache.java
new file mode 100644
index 000000000000..75b5a9910f7a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSCache.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 12/7/12
+*/
+public class FSCache {
+
+ public static final FSCache NO_CACHE = new FSCache() {
+ @Nullable
+ @Override
+ public File[] getChildren(File file) {
+ return file.listFiles();
+ }
+ };
+
+ private static final File[] NULL_VALUE = new File[0];
+ private static final File[] EMPTY_FILE_ARRAY = new File[0];
+ private final Map<File, File[]> myMap = new THashMap<File, File[]>();
+
+ @Nullable
+ public File[] getChildren(File file) {
+ synchronized (myMap) {
+ final File[] children = myMap.get(file);
+ if (children != null) {
+ return children == NULL_VALUE? null : children;
+ }
+ final File[] files = file.listFiles();
+ myMap.put(file, files == null? NULL_VALUE : (files.length == 0? EMPTY_FILE_ARRAY : files));
+ return files;
+ }
+ }
+
+ public void clear() {
+ synchronized (myMap) {
+ myMap.clear();
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
new file mode 100644
index 000000000000..3fd4fc9d0099
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileSystemUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+import org.jetbrains.jps.model.java.JpsJavaClasspathKind;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 7/8/12
+ */
+public class FSOperations {
+ public static final Key<Set<File>> ALL_OUTPUTS_KEY = Key.create("_all_project_output_dirs_");
+
+ public static void markDirty(CompileContext context, final File file) throws IOException {
+ final JavaSourceRootDescriptor rd = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
+ if (rd != null) {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ pd.fsState.markDirty(context, file, rd, pd.timestamps.getStorage(), false);
+ }
+ }
+
+ public static void markDirtyIfNotDeleted(CompileContext context, final File file) throws IOException {
+ final JavaSourceRootDescriptor rd = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
+ if (rd != null) {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ pd.fsState.markDirtyIfNotDeleted(context, file, rd, pd.timestamps.getStorage());
+ }
+ }
+
+ public static void markDeleted(CompileContext context, File file) throws IOException {
+ final JavaSourceRootDescriptor rd = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
+ if (rd != null) {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ pd.fsState.registerDeleted(rd.target, file, pd.timestamps.getStorage());
+ }
+ }
+
+ public static void markDirty(CompileContext context, final ModuleChunk chunk, @Nullable FileFilter filter) throws IOException {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ markDirtyFiles(context, target, pd.timestamps.getStorage(), true, null, filter);
+ }
+ }
+
+ public static void markDirtyRecursively(CompileContext context, ModuleChunk chunk) throws IOException {
+ Set<JpsModule> modules = chunk.getModules();
+ Set<ModuleBuildTarget> targets = chunk.getTargets();
+ final Set<ModuleBuildTarget> dirtyTargets = new HashSet<ModuleBuildTarget>(targets);
+
+ // now mark all modules that depend on dirty modules
+ final JpsJavaClasspathKind classpathKind = JpsJavaClasspathKind.compile(chunk.containsTests());
+ boolean found = false;
+ for (BuildTargetChunk targetChunk : context.getProjectDescriptor().getBuildTargetIndex().getSortedTargetChunks(context)) {
+ if (!found) {
+ if (targetChunk.getTargets().equals(chunk.getTargets())) {
+ found = true;
+ }
+ }
+ else {
+ for (final BuildTarget<?> target : targetChunk.getTargets()) {
+ if (target instanceof ModuleBuildTarget) {
+ final Set<JpsModule> deps = getDependentModulesRecursively(((ModuleBuildTarget)target).getModule(), classpathKind);
+ if (Utils.intersects(deps, modules)) {
+ for (BuildTarget<?> buildTarget : targetChunk.getTargets()) {
+ if (buildTarget instanceof ModuleBuildTarget) {
+ dirtyTargets.add((ModuleBuildTarget)buildTarget);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ final Timestamps timestamps = context.getProjectDescriptor().timestamps.getStorage();
+ for (ModuleBuildTarget target : dirtyTargets) {
+ markDirtyFiles(context, target, timestamps, true, null, null);
+ }
+
+ if (context.isMake()) {
+ // mark as non-incremental only the module that triggered non-incremental change
+ for (ModuleBuildTarget target : targets) {
+ context.markNonIncremental(target);
+ }
+ }
+ }
+
+ private static Set<JpsModule> getDependentModulesRecursively(final JpsModule module, final JpsJavaClasspathKind kind) {
+ return JpsJavaExtensionService.dependencies(module).includedIn(kind).recursively().exportedOnly().getModules();
+ }
+
+ public static void processFilesToRecompile(CompileContext context, ModuleChunk chunk, FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor) throws IOException {
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ processFilesToRecompile(context, target, processor);
+ }
+ }
+
+ public static void processFilesToRecompile(CompileContext context, ModuleBuildTarget target, FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor) throws IOException {
+ context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor);
+ }
+
+ static void markDirtyFiles(CompileContext context,
+ BuildTarget<?> target,
+ Timestamps timestamps,
+ boolean forceMarkDirty,
+ @Nullable THashSet<File> currentFiles,
+ @Nullable FileFilter filter) throws IOException {
+ for (BuildRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) {
+ if (!rd.getRootFile().exists() ||
+ //temp roots are managed by compilers themselves
+ (rd instanceof JavaSourceRootDescriptor && ((JavaSourceRootDescriptor)rd).isTemp)) {
+ continue;
+ }
+ if (filter == null) {
+ context.getProjectDescriptor().fsState.clearRecompile(rd);
+ }
+ final FSCache fsCache = rd.canUseFileCache() ? context.getProjectDescriptor().getFSCache() : FSCache.NO_CACHE;
+ traverseRecursively(context, rd, rd.getRootFile(), timestamps, forceMarkDirty, currentFiles, filter, fsCache);
+ }
+ }
+
+ private static void traverseRecursively(CompileContext context,
+ final BuildRootDescriptor rd,
+ final File file,
+ @NotNull final Timestamps tsStorage,
+ final boolean forceDirty,
+ @Nullable Set<File> currentFiles, @Nullable FileFilter filter, @NotNull FSCache fsCache) throws IOException {
+ if (context.getProjectDescriptor().getIgnoredFileIndex().isIgnored(file.getName())) {
+ return;
+ }
+ final File[] children = fsCache.getChildren(file);
+ if (children != null) { // is directory
+ if (children.length > 0 && !rd.getExcludedRoots().contains(file)) {
+ for (File child : children) {
+ traverseRecursively(context, rd, child, tsStorage, forceDirty, currentFiles, filter, fsCache);
+ }
+ }
+ }
+ else { // is file
+ if (filter == null || filter.accept(file)) {
+ boolean markDirty = forceDirty;
+ if (!markDirty) {
+ markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file);
+ }
+ if (markDirty) {
+ // if it is full project rebuild, all storages are already completely cleared;
+ // so passing null because there is no need to access the storage to clear non-existing data
+ final Timestamps marker = context.isProjectRebuild() ? null : tsStorage;
+ context.getProjectDescriptor().fsState.markDirty(context, file, rd, marker, false);
+ }
+ if (currentFiles != null) {
+ currentFiles.add(file);
+ }
+ }
+ }
+ }
+
+ public static void pruneEmptyDirs(CompileContext context, @Nullable final Set<File> dirsToDelete) {
+ if (dirsToDelete == null || dirsToDelete.isEmpty()) return;
+
+ Set<File> doNotDelete = ALL_OUTPUTS_KEY.get(context);
+ if (doNotDelete == null) {
+ doNotDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ for (BuildTarget<?> target : context.getProjectDescriptor().getBuildTargetIndex().getAllTargets()) {
+ doNotDelete.addAll(target.getOutputRoots(context));
+ }
+ ALL_OUTPUTS_KEY.set(context, doNotDelete);
+ }
+
+ Set<File> additionalDirs = null;
+ Set<File> toDelete = dirsToDelete;
+ while (toDelete != null) {
+ for (File file : toDelete) {
+ // important: do not force deletion if the directory is not empty!
+ final boolean deleted = !doNotDelete.contains(file) && file.delete();
+ if (deleted) {
+ final File parentFile = file.getParentFile();
+ if (parentFile != null) {
+ if (additionalDirs == null) {
+ additionalDirs = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ }
+ additionalDirs.add(parentFile);
+ }
+ }
+ }
+ toDelete = additionalDirs;
+ additionalDirs = null;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
new file mode 100644
index 000000000000..f2cf3f0c52fe
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
@@ -0,0 +1,1116 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.LowMemoryWatcher;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.concurrency.BoundedTaskExecutor;
+import com.intellij.util.containers.ConcurrentHashSet;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.MultiMapBasedOnSet;
+import com.intellij.util.io.MappingFailedException;
+import com.intellij.util.io.PersistentEnumerator;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.api.GlobalOptions;
+import org.jetbrains.jps.api.RequestFuture;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.cmdline.BuildRunner;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor;
+import org.jetbrains.jps.incremental.messages.*;
+import org.jetbrains.jps.incremental.storage.OneToManyPathsMapping;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.service.SharedThreadPool;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public class IncProjectBuilder {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder");
+
+ private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index";
+ private static final boolean GENERATE_CLASSPATH_INDEX = Boolean.parseBoolean(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION, "false"));
+ private static final Key<Set<BuildTarget<?>>> TARGET_WITH_CLEARED_OUTPUT = Key.create("_targets_with_cleared_output_");
+ private static final int MAX_BUILDER_THREADS;
+ static {
+ int maxThreads = 6;
+ try {
+ maxThreads = Math.max(2, Integer.parseInt(System.getProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION, Integer.toString(maxThreads))));
+ }
+ catch (NumberFormatException ignored) {
+ }
+ MAX_BUILDER_THREADS = maxThreads;
+ }
+
+ private final ProjectDescriptor myProjectDescriptor;
+ private final BuilderRegistry myBuilderRegistry;
+ private final Map<String, String> myBuilderParams;
+ private final CanceledStatus myCancelStatus;
+ @Nullable private final Callbacks.ConstantAffectionResolver myConstantSearch;
+ private final List<MessageHandler> myMessageHandlers = new ArrayList<MessageHandler>();
+ private final MessageHandler myMessageDispatcher = new MessageHandler() {
+ public void processMessage(BuildMessage msg) {
+ for (MessageHandler h : myMessageHandlers) {
+ h.processMessage(msg);
+ }
+ }
+ };
+
+ private volatile float myTargetsProcessed = 0.0f;
+ private final float myTotalTargetsWork;
+ private final int myTotalModuleLevelBuilderCount;
+ private final List<Future> myAsyncTasks = Collections.synchronizedList(new ArrayList<Future>());
+
+ public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map<String, String> builderParams, CanceledStatus cs,
+ @Nullable Callbacks.ConstantAffectionResolver constantSearch) {
+ myProjectDescriptor = pd;
+ myBuilderRegistry = builderRegistry;
+ myBuilderParams = builderParams;
+ myCancelStatus = cs;
+ myConstantSearch = constantSearch;
+ myTotalTargetsWork = pd.getBuildTargetIndex().getAllTargets().size();
+ myTotalModuleLevelBuilderCount = builderRegistry.getModuleLevelBuilderCount();
+ }
+
+ public void addMessageHandler(MessageHandler handler) {
+ myMessageHandlers.add(handler);
+ }
+
+ public void checkUpToDate(CompileScope scope) {
+ CompileContextImpl context = null;
+ try {
+ context = createContext(scope, true, false);
+ final BuildFSState fsState = myProjectDescriptor.fsState;
+ for (BuildTarget<?> target : myProjectDescriptor.getBuildTargetIndex().getAllTargets()) {
+ if (scope.isAffected(target)) {
+ BuildOperations.ensureFSStateInitialized(context, target);
+ final Map<BuildRootDescriptor, Set<File>> toRecompile = fsState.getSourcesToRecompile(context, target);
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
+ synchronized (toRecompile) {
+ for (Set<File> files : toRecompile.values()) {
+ for (File file : files) {
+ if (scope.isAffected(target, file)) {
+ // this will serve as a marker that compiler has work to do
+ myMessageDispatcher.processMessage(DoneSomethingNotification.INSTANCE);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.info(e);
+ // this will serve as a marker that compiler has work to do
+ myMessageDispatcher.processMessage(DoneSomethingNotification.INSTANCE);
+ }
+ finally {
+ if (context != null) {
+ flushContext(context);
+ }
+ }
+ }
+
+
+ public void build(CompileScope scope, final boolean isMake, final boolean isProjectRebuild, boolean forceCleanCaches)
+ throws RebuildRequestedException {
+
+ final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ myProjectDescriptor.dataManager.flush(false);
+ myProjectDescriptor.timestamps.getStorage().force();
+ }
+ });
+ CompileContextImpl context = null;
+ try {
+ context = createContext(scope, isMake, isProjectRebuild);
+ runBuild(context, forceCleanCaches);
+ myProjectDescriptor.dataManager.saveVersion();
+ }
+ catch (ProjectBuildException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof PersistentEnumerator.CorruptedException ||
+ cause instanceof MappingFailedException ||
+ cause instanceof IOException) {
+ myMessageDispatcher.processMessage(new CompilerMessage(
+ "", BuildMessage.Kind.INFO,
+ "Internal caches are corrupted or have outdated format, forcing project rebuild: " +
+ e.getMessage())
+ );
+ throw new RebuildRequestedException(cause);
+ }
+ else {
+ if (cause == null) {
+ // some builder desided to stop the build
+ // report optional progress message if exists
+ final String msg = e.getMessage();
+ if (!StringUtil.isEmpty(msg)) {
+ myMessageDispatcher.processMessage(new ProgressMessage(msg));
+ }
+ }
+ else {
+ // the reason for the build stop is unexpected internal error, report it
+ myMessageDispatcher.processMessage(new CompilerMessage("", cause));
+ }
+ }
+ }
+ finally {
+ memWatcher.stop();
+ flushContext(context);
+ // wait for the async tasks
+ synchronized (myAsyncTasks) {
+ for (Future task : myAsyncTasks) {
+ try {
+ task.get();
+ }
+ catch (Throwable th) {
+ LOG.info(th);
+ }
+ }
+ }
+ }
+ }
+
+ private static void flushContext(CompileContext context) {
+ if (context != null) {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ pd.timestamps.getStorage().force();
+ pd.dataManager.flush(false);
+ }
+ final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context);
+ if (descriptor != null) {
+ try {
+ final RequestFuture future = descriptor.client.sendShutdownRequest();
+ future.waitFor(500L, TimeUnit.MILLISECONDS);
+ }
+ finally {
+ // ensure process is not running
+ descriptor.process.destroyProcess();
+ }
+ ExternalJavacDescriptor.KEY.set(context, null);
+ }
+ //cleanupJavacNameTable();
+ }
+
+ //private static boolean ourClenupFailed = false;
+
+ //private static void cleanupJavacNameTable() {
+ // try {
+ // if (JavaBuilder.USE_EMBEDDED_JAVAC && !ourClenupFailed) {
+ // final Field freelistField = Class.forName("com.sun.tools.javac.util.Name$Table").getDeclaredField("freelist");
+ // freelistField.setAccessible(true);
+ // freelistField.set(null, com.sun.tools.javac.util.List.nil());
+ // }
+ // }
+ // catch (Throwable e) {
+ // ourClenupFailed = true;
+ // //LOG.info(e);
+ // }
+ //}
+
+ private void runBuild(CompileContextImpl context, boolean forceCleanCaches) throws ProjectBuildException {
+ context.setDone(0.0f);
+
+ LOG.info("Building project; isRebuild:" +
+ context.isProjectRebuild() +
+ "; isMake:" +
+ context.isMake() +
+ " parallel compilation:" +
+ BuildRunner.PARALLEL_BUILD_ENABLED);
+
+ for (TargetBuilder builder : myBuilderRegistry.getTargetBuilders()) {
+ builder.buildStarted(context);
+ }
+ for (ModuleLevelBuilder builder : myBuilderRegistry.getModuleLevelBuilders()) {
+ builder.buildStarted(context);
+ }
+
+ try {
+ if (context.isProjectRebuild() || forceCleanCaches) {
+ cleanOutputRoots(context);
+ }
+
+ context.processMessage(new ProgressMessage("Running 'before' tasks"));
+ runTasks(context, myBuilderRegistry.getBeforeTasks());
+
+ context.processMessage(new ProgressMessage("Checking sources"));
+ buildChunks(context);
+
+ context.processMessage(new ProgressMessage("Running 'after' tasks"));
+ runTasks(context, myBuilderRegistry.getAfterTasks());
+
+ // cleanup output roots layout, commented for efficiency
+ //final ModuleOutputRootsLayout outputRootsLayout = context.getDataManager().getOutputRootsLayout();
+ //try {
+ // final Iterator<String> keysIterator = outputRootsLayout.getKeysIterator();
+ // final Map<String, JpsModule> modules = myProjectDescriptor.project.getModules();
+ // while (keysIterator.hasNext()) {
+ // final String moduleName = keysIterator.next();
+ // if (modules.containsKey(moduleName)) {
+ // outputRootsLayout.remove(moduleName);
+ // }
+ // }
+ //}
+ //catch (IOException e) {
+ // throw new ProjectBuildException(e);
+ //}
+ }
+ finally {
+ for (TargetBuilder builder : myBuilderRegistry.getTargetBuilders()) {
+ builder.buildFinished(context);
+ }
+ for (ModuleLevelBuilder builder : myBuilderRegistry.getModuleLevelBuilders()) {
+ builder.buildFinished(context);
+ }
+ context.processMessage(new ProgressMessage("Finished, saving caches..."));
+ }
+
+ }
+
+ private CompileContextImpl createContext(CompileScope scope, boolean isMake, final boolean isProjectRebuild)
+ throws ProjectBuildException {
+ final CompileContextImpl context = new CompileContextImpl(scope, myProjectDescriptor, isMake, isProjectRebuild, myMessageDispatcher,
+ myBuilderParams, myCancelStatus
+ );
+ // in project rebuild mode performance gain is hard to observe, so it is better to save memory
+ // in make mode it is critical to traverse file system as fast as possible, so we choose speed over memory savings
+ myProjectDescriptor.setFSCache(isProjectRebuild? FSCache.NO_CACHE : new FSCache());
+ JavaBuilderUtil.CONSTANT_SEARCH_SERVICE.set(context, myConstantSearch);
+ return context;
+ }
+
+ private void cleanOutputRoots(CompileContext context) throws ProjectBuildException {
+ // whole project is affected
+ ProjectDescriptor projectDescriptor = context.getProjectDescriptor();
+ JpsJavaCompilerConfiguration configuration =
+ JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(projectDescriptor.getProject());
+ final boolean shouldClear = configuration.isClearOutputDirectoryOnRebuild();
+ try {
+ if (shouldClear) {
+ clearOutputs(context);
+ }
+ else {
+ for (BuildTarget<?> target : projectDescriptor.getBuildTargetIndex().getAllTargets()) {
+ if (context.getScope().isAffected(target)) {
+ clearOutputFiles(context, target);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException("Error cleaning output files", e);
+ }
+
+ try {
+ projectDescriptor.timestamps.getStorage().clean();
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException("Error cleaning timestamps storage", e);
+ }
+ try {
+ projectDescriptor.dataManager.clean();
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException("Error cleaning compiler storages", e);
+ }
+ myProjectDescriptor.fsState.clearAll();
+ }
+
+ public static void clearOutputFiles(CompileContext context, BuildTarget<?> target) throws IOException {
+ final SourceToOutputMapping map = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
+ final THashSet<File> dirsToDelete = target instanceof ModuleBasedTarget? new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY) : null;
+ for (String srcPath : map.getSources()) {
+ final Collection<String> outs = map.getOutputs(srcPath);
+ if (outs != null && !outs.isEmpty()) {
+ for (String out : outs) {
+ final File outFile = new File(out);
+ final boolean deleted = outFile.delete();
+ if (deleted && dirsToDelete != null) {
+ final File parent = outFile.getParentFile();
+ if (parent != null) {
+ dirsToDelete.add(parent);
+ }
+ }
+ }
+ context.processMessage(new FileDeletedEvent(outs));
+ }
+ }
+ registerTargetsWithClearedOutput(context, Collections.singletonList(target));
+ if (dirsToDelete != null) {
+ FSOperations.pruneEmptyDirs(context, dirsToDelete);
+ }
+ }
+
+ private static void registerTargetsWithClearedOutput(CompileContext context, Collection<? extends BuildTarget<?>> targets) {
+ synchronized (TARGET_WITH_CLEARED_OUTPUT) {
+ Set<BuildTarget<?>> data = context.getUserData(TARGET_WITH_CLEARED_OUTPUT);
+ if (data == null) {
+ data = new THashSet<BuildTarget<?>>();
+ context.putUserData(TARGET_WITH_CLEARED_OUTPUT, data);
+ }
+ data.addAll(targets);
+ }
+ }
+
+ private static boolean isTargetOutputCleared(CompileContext context, BuildTarget<?> target) {
+ synchronized (TARGET_WITH_CLEARED_OUTPUT) {
+ Set<BuildTarget<?>> data = context.getUserData(TARGET_WITH_CLEARED_OUTPUT);
+ return data != null && data.contains(target);
+ }
+ }
+
+ private void clearOutputs(CompileContext context) throws ProjectBuildException, IOException {
+ final MultiMap<File, BuildTarget<?>> rootsToDelete = new MultiMapBasedOnSet<File, BuildTarget<?>>();
+ final Set<File> allSourceRoots = new HashSet<File>();
+
+ ProjectDescriptor projectDescriptor = context.getProjectDescriptor();
+ List<? extends BuildTarget<?>> allTargets = projectDescriptor.getBuildTargetIndex().getAllTargets();
+ for (BuildTarget<?> target : allTargets) {
+ if (context.getScope().isAffected(target)) {
+ final Collection<File> outputs = target.getOutputRoots(context);
+ for (File file : outputs) {
+ rootsToDelete.putValue(file, target);
+ }
+ }
+ }
+
+ ModuleExcludeIndex moduleIndex = projectDescriptor.getModuleExcludeIndex();
+ for (BuildTarget<?> target : allTargets) {
+ for (BuildRootDescriptor descriptor : projectDescriptor.getBuildRootIndex().getTargetRoots(target, context)) {
+ // excluding from checks roots with generated sources; because it is safe to delete generated stuff
+ if (!descriptor.isGenerated()) {
+ File rootFile = descriptor.getRootFile();
+ //some roots aren't marked by as generated but in fact they are produced by some builder and it's safe to remove them.
+ //However if a root isn't excluded it means that its content will be shown in 'Project View' and an user can create new files under it so it would be dangerous to clean such roots
+ if (moduleIndex.isInContent(rootFile) && !moduleIndex.isExcluded(rootFile)) {
+ allSourceRoots.add(rootFile);
+ }
+ }
+ }
+ }
+
+ // check that output and source roots are not overlapping
+ final List<File> filesToDelete = new ArrayList<File>();
+ for (Map.Entry<File, Collection<BuildTarget<?>>> entry : rootsToDelete.entrySet()) {
+ context.checkCanceled();
+ boolean okToDelete = true;
+ final File outputRoot = entry.getKey();
+ if (JpsPathUtil.isUnder(allSourceRoots, outputRoot)) {
+ okToDelete = false;
+ }
+ else {
+ final Set<File> _outRoot = Collections.singleton(outputRoot);
+ for (File srcRoot : allSourceRoots) {
+ if (JpsPathUtil.isUnder(_outRoot, srcRoot)) {
+ okToDelete = false;
+ break;
+ }
+ }
+ }
+ if (okToDelete) {
+ // do not delete output root itself to avoid lots of unnecessary "roots_changed" events in IDEA
+ final File[] children = outputRoot.listFiles();
+ if (children != null) {
+ filesToDelete.addAll(Arrays.asList(children));
+ }
+ else if (outputRoot.isFile()) {
+ filesToDelete.add(outputRoot);
+ }
+ registerTargetsWithClearedOutput(context, entry.getValue());
+ }
+ else {
+ context.processMessage(new CompilerMessage(
+ "", BuildMessage.Kind.WARNING, "Output path " + outputRoot.getPath() + " intersects with a source root. Only files that were created by build will be cleaned.")
+ );
+ // clean only those files we are aware of
+ for (BuildTarget<?> target : entry.getValue()) {
+ clearOutputFiles(context, target);
+ }
+ }
+ }
+
+ context.processMessage(new ProgressMessage("Cleaning output directories..."));
+ myAsyncTasks.add(
+ FileUtil.asyncDelete(filesToDelete)
+ );
+ }
+
+ private static void runTasks(CompileContext context, final List<BuildTask> tasks) throws ProjectBuildException {
+ for (BuildTask task : tasks) {
+ task.build(context);
+ }
+ }
+
+ private void buildChunks(final CompileContextImpl context) throws ProjectBuildException {
+ try {
+ if (BuildRunner.PARALLEL_BUILD_ENABLED) {
+ new BuildParallelizer(context).buildInParallel();
+ }
+ else {
+ // non-parallel build
+ final CompileScope scope = context.getScope();
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final BuildTargetIndex targetIndex = pd.getBuildTargetIndex();
+
+ for (BuildTargetChunk chunk : targetIndex.getSortedTargetChunks(context)) {
+ try {
+ buildChunkIfAffected(context, scope, chunk);
+ }
+ finally {
+ context.updateCompilationStartStamp();
+ pd.dataManager.closeSourceToOutputStorages(Collections.singleton(chunk));
+ pd.dataManager.flush(true);
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException(e);
+ }
+ }
+
+ private static class BuildChunkTask {
+ private final BuildTargetChunk myChunk;
+ private final Set<BuildChunkTask> myNotBuiltDependencies = new THashSet<BuildChunkTask>();
+ private final List<BuildChunkTask> myTasksDependsOnThis = new ArrayList<BuildChunkTask>();
+
+ private BuildChunkTask(BuildTargetChunk chunk) {
+ myChunk = chunk;
+ }
+
+ public BuildTargetChunk getChunk() {
+ return myChunk;
+ }
+
+ public boolean isReady() {
+ return myNotBuiltDependencies.isEmpty();
+ }
+
+ public void addDependency(BuildChunkTask dependency) {
+ if (myNotBuiltDependencies.add(dependency)) {
+ dependency.myTasksDependsOnThis.add(this);
+ }
+ }
+
+ public List<BuildChunkTask> markAsFinishedAndGetNextReadyTasks() {
+ List<BuildChunkTask> nextTasks = new SmartList<BuildChunkTask>();
+ for (BuildChunkTask task : myTasksDependsOnThis) {
+ final boolean removed = task.myNotBuiltDependencies.remove(this);
+ LOG.assertTrue(removed, task.getChunk().toString() + " didn't have " + getChunk().toString());
+
+ if (task.isReady()) {
+ nextTasks.add(task);
+ }
+ }
+ return nextTasks;
+ }
+ }
+
+ private class BuildParallelizer {
+ private final BoundedTaskExecutor myParallelBuildExecutor =
+ new BoundedTaskExecutor(SharedThreadPool.getInstance(),
+ Math.min(MAX_BUILDER_THREADS, Math.max(2, Runtime.getRuntime().availableProcessors())));
+ private final CompileContext myContext;
+ private final AtomicReference<Throwable> myException = new AtomicReference<Throwable>();
+ private final Object myQueueLock = new Object();
+ private final CountDownLatch myTasksCountDown;
+ private final List<BuildChunkTask> myTasks;
+
+ private BuildParallelizer(CompileContext context) {
+ myContext = context;
+ final ProjectDescriptor pd = myContext.getProjectDescriptor();
+ final BuildTargetIndex targetIndex = pd.getBuildTargetIndex();
+
+ List<BuildTargetChunk> chunks = targetIndex.getSortedTargetChunks(myContext);
+ myTasks = new ArrayList<BuildChunkTask>(chunks.size());
+ Map<BuildTarget<?>, BuildChunkTask> targetToTask = new THashMap<BuildTarget<?>, BuildChunkTask>();
+ for (BuildTargetChunk chunk : chunks) {
+ BuildChunkTask task = new BuildChunkTask(chunk);
+ myTasks.add(task);
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ targetToTask.put(target, task);
+ }
+ }
+
+ for (BuildChunkTask task : myTasks) {
+ for (BuildTarget<?> target : task.getChunk().getTargets()) {
+ for (BuildTarget<?> dependency : targetIndex.getDependencies(target, myContext)) {
+ BuildChunkTask depTask = targetToTask.get(dependency);
+ if (depTask != null && depTask != task) {
+ task.addDependency(depTask);
+ }
+ }
+ }
+ }
+
+ myTasksCountDown = new CountDownLatch(myTasks.size());
+ }
+
+ public void buildInParallel() throws IOException, ProjectBuildException {
+ List<BuildChunkTask> initialTasks = new ArrayList<BuildChunkTask>();
+ for (BuildChunkTask task : myTasks) {
+ if (task.isReady()) {
+ initialTasks.add(task);
+ }
+ }
+ queueTasks(initialTasks);
+
+ try {
+ myTasksCountDown.await();
+ }
+ catch (InterruptedException e) {
+ LOG.info(e);
+ }
+
+ final Throwable throwable = myException.get();
+ if (throwable instanceof ProjectBuildException) {
+ throw (ProjectBuildException)throwable;
+ }
+ else if (throwable != null) {
+ throw new ProjectBuildException(throwable);
+ }
+ }
+
+ private void queueTasks(List<BuildChunkTask> tasks) {
+ List<BuildTargetChunk> chunksToLog = LOG.isDebugEnabled() ? new ArrayList<BuildTargetChunk>() : null;
+ for (BuildChunkTask task : tasks) {
+ if (chunksToLog != null) {
+ chunksToLog.add(task.getChunk());
+ }
+ queueTask(task);
+ }
+
+ if (chunksToLog != null && !chunksToLog.isEmpty()) {
+ final StringBuilder logBuilder = new StringBuilder("Queuing " + chunksToLog.size() + " chunks in parallel: ");
+ Collections.sort(chunksToLog, new Comparator<BuildTargetChunk>() {
+ public int compare(final BuildTargetChunk o1, final BuildTargetChunk o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ });
+ for (BuildTargetChunk chunk : chunksToLog) {
+ logBuilder.append(chunk.toString()).append("; ");
+ }
+ LOG.debug(logBuilder.toString());
+ }
+ }
+
+ private void queueTask(final BuildChunkTask task) {
+ final CompileContext chunkLocalContext = createContextWrapper(myContext);
+ myParallelBuildExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ try {
+ if (myException.get() == null) {
+ buildChunkIfAffected(chunkLocalContext, myContext.getScope(), task.getChunk());
+ }
+ }
+ finally {
+ myContext.updateCompilationStartStamp();
+ myProjectDescriptor.dataManager.closeSourceToOutputStorages(Collections.singletonList(task.getChunk()));
+ myProjectDescriptor.dataManager.flush(true);
+ }
+ }
+ catch (Throwable e) {
+ myException.compareAndSet(null, e);
+ LOG.info(e);
+ }
+ finally {
+ LOG.debug("Finished compilation of " + task.getChunk().toString());
+ myTasksCountDown.countDown();
+ List<BuildChunkTask> nextTasks;
+ synchronized (myQueueLock) {
+ nextTasks = task.markAsFinishedAndGetNextReadyTasks();
+ }
+ if (!nextTasks.isEmpty()) {
+ queueTasks(nextTasks);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private void buildChunkIfAffected(CompileContext context, CompileScope scope, BuildTargetChunk chunk) throws ProjectBuildException {
+ if (isAffected(scope, chunk)) {
+ buildTargetsChunk(context, chunk);
+ }
+ else {
+ updateDoneFraction(context, chunk.getTargets().size());
+ }
+ }
+
+ private static boolean isAffected(CompileScope scope, BuildTargetChunk chunk) {
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ if (scope.isAffected(target)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean runBuildersForChunk(CompileContext context, final BuildTargetChunk chunk) throws ProjectBuildException, IOException {
+ Set<? extends BuildTarget<?>> targets = chunk.getTargets();
+ if (targets.size() > 1) {
+ Set<ModuleBuildTarget> moduleTargets = new HashSet<ModuleBuildTarget>();
+ for (BuildTarget<?> target : targets) {
+ if (target instanceof ModuleBuildTarget) {
+ moduleTargets.add((ModuleBuildTarget)target);
+ }
+ else {
+ context.processMessage(new CompilerMessage(
+ "", BuildMessage.Kind.ERROR, "Cannot build " + target.getPresentableName() + " because it is included into a circular dependency")
+ );
+ return false;
+ }
+ }
+
+ return runModuleLevelBuilders(context, new ModuleChunk(moduleTargets));
+ }
+
+ final BuildTarget<?> target = targets.iterator().next();
+ if (target instanceof ModuleBuildTarget) {
+ return runModuleLevelBuilders(context, new ModuleChunk(Collections.singleton((ModuleBuildTarget)target)));
+ }
+
+ final List<TargetBuilder<?, ?>> builders = BuilderRegistry.getInstance().getTargetBuilders();
+ for (TargetBuilder<?, ?> builder : builders) {
+ BuildOperations.buildTarget(target, context, builder);
+ updateDoneFraction(context, 1.0f / builders.size());
+ }
+ return true;
+ }
+
+ private void updateDoneFraction(CompileContext context, final float delta) {
+ myTargetsProcessed += delta;
+ float processed = myTargetsProcessed;
+ context.setDone(processed / myTotalTargetsWork);
+ }
+
+ private void buildTargetsChunk(CompileContext context, final BuildTargetChunk chunk) throws ProjectBuildException {
+ boolean doneSomething;
+ try {
+ Utils.ERRORS_DETECTED_KEY.set(context, Boolean.FALSE);
+
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ BuildOperations.ensureFSStateInitialized(context, target);
+ }
+
+ doneSomething = processDeletedPaths(context, chunk.getTargets());
+
+ myProjectDescriptor.fsState.beforeChunkBuildStart(context, chunk);
+
+ doneSomething |= runBuildersForChunk(context, chunk);
+
+ onChunkBuildComplete(context, chunk);
+
+ //if (doneSomething && GENERATE_CLASSPATH_INDEX) {
+ // myAsyncTasks.add(SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
+ // @Override
+ // public void run() {
+ // createClasspathIndex(chunk);
+ // }
+ // }));
+ //}
+ }
+ catch (ProjectBuildException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new ProjectBuildException(e);
+ }
+ finally {
+ for (BuildRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().clearTempRoots(context)) {
+ context.getProjectDescriptor().fsState.clearRecompile(rd);
+ }
+ try {
+ // restore deleted paths that were not processed by 'integrate'
+ final Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(context);
+ if (map != null) {
+ for (Map.Entry<BuildTarget<?>, Collection<String>> entry : map.entrySet()) {
+ final BuildTarget<?> target = entry.getKey();
+ final Collection<String> paths = entry.getValue();
+ if (paths != null) {
+ for (String path : paths) {
+ myProjectDescriptor.fsState.registerDeleted(target, new File(path), null);
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ //noinspection ThrowFromFinallyBlock
+ throw new ProjectBuildException(e);
+ }
+ finally {
+ Utils.REMOVED_SOURCES_KEY.set(context, null);
+ }
+ }
+ }
+
+ private static void createClasspathIndex(final BuildTargetChunk chunk) {
+ final Set<File> outputDirs = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ if (target instanceof ModuleBuildTarget) {
+ File outputDir = ((ModuleBuildTarget)target).getOutputDir();
+ if (outputDir != null && outputDirs.add(outputDir)) {
+ try {
+ BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outputDir, CLASSPATH_INDEX_FINE_NAME)));
+ try {
+ writeIndex(writer, outputDir, "");
+ }
+ finally {
+ writer.close();
+ }
+ }
+ catch (IOException e) {
+ // Ignore. Failed to create optional classpath index
+ }
+ }
+ }
+ }
+ }
+
+ private static void writeIndex(final BufferedWriter writer, final File file, final String path) throws IOException {
+ writer.write(path);
+ writer.write('\n');
+ final File[] files = file.listFiles();
+ if (files != null) {
+ for (File child : files) {
+ final String _path = path.isEmpty() ? child.getName() : path + "/" + child.getName();
+ writeIndex(writer, child, _path);
+ }
+ }
+ }
+
+
+ private boolean processDeletedPaths(CompileContext context, final Set<? extends BuildTarget<?>> targets) throws ProjectBuildException {
+ boolean doneSomething = false;
+ try {
+ // cleanup outputs
+ final Map<BuildTarget<?>, Collection<String>> targetToRemovedSources = new HashMap<BuildTarget<?>, Collection<String>>();
+
+ final THashSet<File> dirsToDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ for (BuildTarget<?> target : targets) {
+
+ final Collection<String> deletedPaths = myProjectDescriptor.fsState.getAndClearDeletedPaths(target);
+ if (deletedPaths.isEmpty()) {
+ continue;
+ }
+ targetToRemovedSources.put(target, deletedPaths);
+ if (isTargetOutputCleared(context, target)) {
+ continue;
+ }
+
+ final boolean shouldPruneEmptyDirs = target instanceof ModuleBasedTarget;
+ final SourceToOutputMapping sourceToOutputStorage = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
+ final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ // actually delete outputs associated with removed paths
+ for (String deletedSource : deletedPaths) {
+ // deleting outputs corresponding to non-existing source
+ final Collection<String> outputs = sourceToOutputStorage.getOutputs(deletedSource);
+
+ if (outputs != null && !outputs.isEmpty()) {
+ if (logger.isEnabled()) {
+ logger.logDeletedFiles(outputs);
+ }
+
+ for (String output : outputs) {
+ final File outFile = new File(output);
+ final boolean deleted = outFile.delete();
+ if (deleted) {
+ doneSomething = true;
+ if (shouldPruneEmptyDirs) {
+ final File parent = outFile.getParentFile();
+ if (parent != null) {
+ dirsToDelete.add(parent);
+ }
+ }
+ }
+ }
+ context.processMessage(new FileDeletedEvent(outputs));
+ }
+
+ if (target instanceof ModuleBuildTarget) {
+ // check if deleted source was associated with a form
+ final OneToManyPathsMapping sourceToFormMap = context.getProjectDescriptor().dataManager.getSourceToFormMap();
+ final Collection<String> boundForms = sourceToFormMap.getState(deletedSource);
+ if (boundForms != null) {
+ for (String formPath : boundForms) {
+ final File formFile = new File(formPath);
+ if (formFile.exists()) {
+ FSOperations.markDirty(context, formFile);
+ }
+ }
+ sourceToFormMap.remove(deletedSource);
+ }
+ }
+ }
+ }
+ if (!targetToRemovedSources.isEmpty()) {
+ final Map<BuildTarget<?>, Collection<String>> existing = Utils.REMOVED_SOURCES_KEY.get(context);
+ if (existing != null) {
+ for (Map.Entry<BuildTarget<?>, Collection<String>> entry : existing.entrySet()) {
+ final Collection<String> paths = targetToRemovedSources.get(entry.getKey());
+ if (paths != null) {
+ paths.addAll(entry.getValue());
+ }
+ else {
+ targetToRemovedSources.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ Utils.REMOVED_SOURCES_KEY.set(context, targetToRemovedSources);
+ }
+
+ FSOperations.pruneEmptyDirs(context, dirsToDelete);
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException(e);
+ }
+ return doneSomething;
+ }
+
+ // return true if changed something, false otherwise
+ private boolean runModuleLevelBuilders(final CompileContext context, final ModuleChunk chunk) throws ProjectBuildException, IOException {
+ for (BuilderCategory category : BuilderCategory.values()) {
+ for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
+ builder.chunkBuildStarted(context, chunk);
+ }
+ }
+
+ boolean doneSomething = false;
+ boolean rebuildFromScratchRequested = false;
+ float stageCount = myTotalModuleLevelBuilderCount;
+ final int modulesInChunk = chunk.getModules().size();
+ int buildersPassed = 0;
+ boolean nextPassRequired;
+ ChunkBuildOutputConsumerImpl outputConsumer = new ChunkBuildOutputConsumerImpl(context);
+ try {
+ do {
+ nextPassRequired = false;
+ myProjectDescriptor.fsState.beforeNextRoundStart(context, chunk);
+
+ DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder =
+ new DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) {
+ @Override
+ public void processDirtyFiles(@NotNull FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor)
+ throws IOException {
+ FSOperations.processFilesToRecompile(context, chunk, processor);
+ }
+ };
+ if (!context.isProjectRebuild()) {
+ final Map<ModuleBuildTarget, Set<File>> cleanedSources = BuildOperations
+ .cleanOutputsCorrespondingToChangedFiles(context, dirtyFilesHolder);
+ for (Map.Entry<ModuleBuildTarget, Set<File>> entry : cleanedSources.entrySet()) {
+ final ModuleBuildTarget target = entry.getKey();
+ final Set<File> files = entry.getValue();
+ if (!files.isEmpty()) {
+ final SourceToOutputMapping mapping = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
+ for (File srcFile : files) {
+ mapping.setOutputs(srcFile.getPath(), Collections.<String>emptyList());
+ }
+ }
+ }
+ }
+
+ BUILDER_CATEGORY_LOOP:
+ for (BuilderCategory category : BuilderCategory.values()) {
+ final List<ModuleLevelBuilder> builders = myBuilderRegistry.getBuilders(category);
+ if (builders.isEmpty()) {
+ continue;
+ }
+
+ for (ModuleLevelBuilder builder : builders) {
+ processDeletedPaths(context, chunk.getTargets());
+ final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk, dirtyFilesHolder, outputConsumer);
+
+ doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE);
+
+ if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) {
+ throw new ProjectBuildException("Builder " + builder.getPresentableName() + " requested build stop");
+ }
+ context.checkCanceled();
+ if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
+ if (!nextPassRequired) {
+ // recalculate basis
+ myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount;
+ stageCount += myTotalModuleLevelBuilderCount;
+ myTargetsProcessed += (buildersPassed * modulesInChunk) / stageCount;
+ }
+ nextPassRequired = true;
+ }
+ else if (buildResult == ModuleLevelBuilder.ExitCode.CHUNK_REBUILD_REQUIRED) {
+ if (!rebuildFromScratchRequested && !context.isProjectRebuild()) {
+ LOG.info("Builder " + builder.getPresentableName() + " requested rebuild of module chunk " + chunk.getName());
+ // allow rebuild from scratch only once per chunk
+ rebuildFromScratchRequested = true;
+ try {
+ // forcibly mark all files in the chunk dirty
+ context.getProjectDescriptor().fsState.clearContextRoundData(context);
+ FSOperations.markDirty(context, chunk, null);
+ // reverting to the beginning
+ myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount;
+ stageCount = myTotalModuleLevelBuilderCount;
+ buildersPassed = 0;
+ nextPassRequired = true;
+ outputConsumer.clear();
+ break BUILDER_CATEGORY_LOOP;
+ }
+ catch (Exception e) {
+ throw new ProjectBuildException(e);
+ }
+ }
+ else {
+ LOG.debug("Builder " + builder.getPresentableName() + " requested second chunk rebuild");
+ }
+ }
+
+ buildersPassed++;
+ updateDoneFraction(context, modulesInChunk / (stageCount));
+ }
+ }
+ }
+ while (nextPassRequired);
+ }
+ finally {
+ for (CompiledClass compiledClass : outputConsumer.getCompiledClasses().values()) {
+ if (compiledClass.isDirty()) {
+ compiledClass.save();
+ }
+ }
+ outputConsumer.fireFileGeneratedEvents();
+ outputConsumer.clear();
+ for (BuilderCategory category : BuilderCategory.values()) {
+ for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
+ builder.chunkBuildFinished(context, chunk);
+ }
+ }
+ }
+
+ return doneSomething;
+ }
+
+ private static void onChunkBuildComplete(CompileContext context, @NotNull BuildTargetChunk chunk) throws IOException {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final BuildFSState fsState = pd.fsState;
+ fsState.clearContextRoundData(context);
+ fsState.clearContextChunk(context);
+
+ BuildOperations.markTargetsUpToDate(context, chunk);
+ }
+
+ private static final Set<Key> GLOBAL_CONTEXT_KEYS = new HashSet<Key>();
+ static {
+ // keys for data that must be visible to all threads
+ GLOBAL_CONTEXT_KEYS.add(ExternalJavacDescriptor.KEY);
+ GLOBAL_CONTEXT_KEYS.add(FSOperations.ALL_OUTPUTS_KEY);
+ GLOBAL_CONTEXT_KEYS.add(TARGET_WITH_CLEARED_OUTPUT);
+ }
+
+ private static CompileContext createContextWrapper(final CompileContext delegate) {
+ final ClassLoader loader = delegate.getClass().getClassLoader();
+ final UserDataHolderBase localDataHolder = new UserDataHolderBase();
+ final Set<Object> deletedKeysSet = new ConcurrentHashSet<Object>();
+ final Class<UserDataHolder> dataHolderInterface = UserDataHolder.class;
+ final Class<MessageHandler> messageHandlerInterface = MessageHandler.class;
+ return (CompileContext)Proxy.newProxyInstance(loader, new Class[]{CompileContext.class}, new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ final Class<?> declaringClass = method.getDeclaringClass();
+ if (dataHolderInterface.equals(declaringClass)) {
+ final Object firstArgument = args[0];
+ final boolean isGlobalContextKey = firstArgument instanceof Key && GLOBAL_CONTEXT_KEYS.contains((Key)firstArgument);
+ if (!isGlobalContextKey) {
+ final boolean isWriteOperation = args.length == 2 /*&& void.class.equals(method.getReturnType())*/;
+ if (isWriteOperation) {
+ if (args[1] == null) {
+ deletedKeysSet.add(firstArgument);
+ }
+ else {
+ deletedKeysSet.remove(firstArgument);
+ }
+ }
+ else {
+ if (deletedKeysSet.contains(firstArgument)) {
+ return null;
+ }
+ }
+ final Object result = method.invoke(localDataHolder, args);
+ if (isWriteOperation || result != null) {
+ return result;
+ }
+ }
+ }
+ else if (messageHandlerInterface.equals(declaringClass)) {
+ final BuildMessage msg = (BuildMessage)args[0];
+ if (msg.getKind() == BuildMessage.Kind.ERROR) {
+ Utils.ERRORS_DETECTED_KEY.set(localDataHolder, Boolean.TRUE);
+ }
+ }
+ try {
+ return method.invoke(delegate, args);
+ }
+ catch (InvocationTargetException e) {
+ final Throwable targetEx = e.getTargetException();
+ if (targetEx instanceof ProjectBuildException) {
+ throw targetEx;
+ }
+ throw e;
+ }
+ }
+ });
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java
new file mode 100644
index 000000000000..42afc58fcbc6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.ModuleBasedTarget;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/12/12
+ */
+public abstract class JVMModuleBuildTarget<R extends BuildRootDescriptor> extends ModuleBasedTarget<R> {
+
+ public JVMModuleBuildTarget(BuildTargetType<? extends JVMModuleBuildTarget<R>> targetType, JpsModule module) {
+ super(targetType, module);
+ }
+
+ @Override
+ public String getId() {
+ return getModule().getName();
+ }
+
+ @NotNull
+ protected Set<File> computeRootExcludes(File root, ModuleExcludeIndex index) {
+ final Collection<File> moduleExcludes = index.getModuleExcludes(getModule());
+ if (moduleExcludes.isEmpty()) {
+ return Collections.emptySet();
+ }
+ final Set<File> excludes = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ for (File excluded : moduleExcludes) {
+ if (FileUtil.isAncestor(root, excluded, true)) {
+ excludes.add(excluded);
+ }
+ }
+ return excludes;
+ }
+
+
+ @Override
+ public R findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
+ final List<R> descriptors = rootIndex.getRootDescriptors(
+ new File(rootId), Collections.singletonList((BuildTargetType<? extends JVMModuleBuildTarget<R>>)getTargetType()), null
+ );
+ return ContainerUtil.getFirstItem(descriptors);
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
new file mode 100644
index 000000000000..f8f4ae3ae6d2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder;
+import org.jetbrains.jps.incremental.instrumentation.RmiStubsGenerator;
+import org.jetbrains.jps.incremental.java.JavaBuilder;
+import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JavaBuilderService extends BuilderService {
+ @Override
+ public List<? extends BuildTargetType<?>> getTargetTypes() {
+ final ArrayList<BuildTargetType<?>> types = new ArrayList<BuildTargetType<?>>();
+ types.addAll(JavaModuleBuildTargetType.ALL_TYPES);
+ types.addAll(ResourcesTargetType.ALL_TYPES);
+ return types;
+ }
+
+ @NotNull
+ @Override
+ public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
+ return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()), new NotNullInstrumentingBuilder(), new RmiStubsGenerator());
+ }
+
+ @NotNull
+ @Override
+ public List<? extends TargetBuilder<?, ?>> createBuilders() {
+ return Arrays.asList(new ResourcesBuilder());
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/LineOutputWriter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/LineOutputWriter.java
new file mode 100644
index 000000000000..db3a60ff09fb
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/LineOutputWriter.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 9/24/11
+*/
+public abstract class LineOutputWriter extends Writer {
+ private final LineParser myLineParser = new LineParser();
+
+ public void write(int c) {
+ processData(new CharSequenceIterator(c));
+ }
+
+ public void write(char[] cbuf) {
+ processData(new CharSequenceIterator(cbuf));
+ }
+
+ public void write(String str) {
+ processData(new CharSequenceIterator(str));
+ }
+
+ public void write(String str, int off, int len) {
+ processData(new CharSequenceIterator(str.subSequence(off, off + len)));
+ }
+
+ public Writer append(CharSequence csq) {
+ processData(new CharSequenceIterator(csq));
+ return this;
+ }
+
+ public Writer append(CharSequence csq, int start, int end) {
+ processData(new CharSequenceIterator(csq.subSequence(start, end)));
+ return this;
+ }
+
+ public Writer append(char c) {
+ processData(new CharSequenceIterator(c));
+ return this;
+ }
+
+ public void write(char[] cbuf, int off, int len) {
+ processData(new CharSequenceIterator(cbuf, off, len));
+ }
+
+ private void processData(CharIterator data) {
+ while (myLineParser.parse(data)) {
+ final String line = myLineParser.getResult();
+ myLineParser.reset();
+ lineAvailable(line);
+ }
+ }
+
+
+ public void flush() throws IOException {
+ }
+
+ public void close() throws IOException {
+ try {
+ if (myLineParser.hasData()) {
+ lineAvailable(myLineParser.getResult());
+ }
+ }
+ finally {
+ myLineParser.reset();
+ }
+ }
+
+ protected abstract void lineAvailable(String line);
+
+ private static interface CharIterator {
+ char nextChar();
+ boolean hasData();
+ }
+
+ private static class LineParser {
+ private final StringBuilder myData = new StringBuilder();
+ private boolean myFoundCR = false;
+
+ public boolean parse(CharIterator it) {
+ while (it.hasData()) {
+ final char ch = it.nextChar();
+ if (ch == '\r') {
+ myFoundCR = true;
+ }
+ else if (ch == '\n') {
+ myFoundCR = false;
+ return true;
+ }
+ else {
+ if (myFoundCR) {
+ myData.append('\r');
+ myFoundCR = false;
+ }
+ myData.append(ch);
+ }
+ }
+ return false;
+ }
+
+ public boolean hasData() {
+ return myData.length() > 0;
+ }
+
+ public String getResult() {
+ return myData.toString();
+ }
+
+ public void reset() {
+ myFoundCR = false;
+ myData.setLength(0);
+ }
+ }
+
+ private static class CharSequenceIterator implements CharIterator {
+ private final CharSequence myChars;
+ private int myCursor = 0;
+
+ CharSequenceIterator(final int ch) {
+ this((char)ch);
+ }
+
+ CharSequenceIterator(final char ch) {
+ this(new SingleCharSequence(ch));
+ }
+
+ CharSequenceIterator(char[] chars) {
+ this(chars, 0, chars.length);
+ }
+
+ CharSequenceIterator(final char[] chars, final int offset, final int length) {
+ this(new ArrayCharSequence(chars, offset, length));
+ }
+
+ CharSequenceIterator(CharSequence sequence) {
+ myChars = sequence;
+ }
+
+ public char nextChar() {
+ return myChars.charAt(myCursor++);
+ }
+
+ public boolean hasData() {
+ return myCursor < myChars.length();
+ }
+ }
+
+ private static class SingleCharSequence implements CharSequence {
+ private final char myCh;
+
+ public SingleCharSequence(char ch) {
+ myCh = ch;
+ }
+
+ public int length() {
+ return 1;
+ }
+
+ public char charAt(int index) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index out of bounds: " + index);
+ }
+ return myCh;
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ throw new RuntimeException("Method subSequence not implemented");
+ }
+ }
+
+ private static class ArrayCharSequence implements CharSequence {
+ private final char[] myChars;
+ private final int myOffset;
+ private final int myLength;
+
+ public ArrayCharSequence(char[] chars, int offset, int length) {
+ myChars = chars;
+ myOffset = offset;
+ myLength = length;
+ }
+
+ public int length() {
+ return myLength;
+ }
+
+ public char charAt(int index) {
+ return myChars[index];
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ return new ArrayCharSequence(myChars, start, end - start);
+ }
+
+ public String toString() {
+ return new String(myChars, myOffset, myLength);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/MessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/MessageHandler.java
new file mode 100644
index 000000000000..c9b87c2b8475
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/MessageHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public interface MessageHandler {
+ MessageHandler DEAF = new MessageHandler() {
+ public void processMessage(BuildMessage msg) {
+ }
+ };
+
+ void processMessage(BuildMessage msg);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
new file mode 100644
index 000000000000..e27534b98d40
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.SmartList;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
+import org.jetbrains.jps.service.JpsServiceManager;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public final class ModuleBuildTarget extends JVMModuleBuildTarget<JavaSourceRootDescriptor> {
+ private final JavaModuleBuildTargetType myTargetType;
+
+ public ModuleBuildTarget(@NotNull JpsModule module, JavaModuleBuildTargetType targetType) {
+ super(targetType, module);
+ myTargetType = targetType;
+ }
+
+ @Nullable
+ public File getOutputDir() {
+ return JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, myTargetType.isTests());
+ }
+
+ @NotNull
+ @Override
+ public Collection<File> getOutputRoots(CompileContext context) {
+ Collection<File> result = new SmartList<File>();
+ final File outputDir = getOutputDir();
+ if (outputDir != null) {
+ result.add(outputDir);
+ }
+ final JpsModule module = getModule();
+ final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(module.getProject());
+ final ProcessorConfigProfile profile = configuration.getAnnotationProcessingProfile(module);
+ if (profile.isEnabled()) {
+ final File annotationOut = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir(module, isTests(), profile);
+ if (annotationOut != null) {
+ result.add(annotationOut);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isTests() {
+ return myTargetType.isTests();
+ }
+
+ @Override
+ public final boolean isCompiledBeforeModuleLevelBuilders() {
+ return false;
+ }
+
+ @Override
+ public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
+ JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(myModule).compileOnly();
+ if (!isTests()) {
+ enumerator.productionOnly();
+ }
+ final ArrayList<BuildTarget<?>> dependencies = new ArrayList<BuildTarget<?>>();
+ enumerator.processModules(new Consumer<JpsModule>() {
+ @Override
+ public void consume(JpsModule module) {
+ dependencies.add(new ModuleBuildTarget(module, myTargetType));
+ }
+ });
+ if (isTests()) {
+ dependencies.add(new ModuleBuildTarget(myModule, JavaModuleBuildTargetType.PRODUCTION));
+ }
+ final Collection<ModuleBasedTarget<?>> moduleBased = targetRegistry.getModuleBasedTargets(
+ getModule(), isTests() ? BuildTargetRegistry.ModuleTargetSelector.TEST : BuildTargetRegistry.ModuleTargetSelector.PRODUCTION
+ );
+ for (ModuleBasedTarget<?> target : moduleBased) {
+ if (target != this && target.isCompiledBeforeModuleLevelBuilders()) {
+ dependencies.add(target);
+ }
+ }
+ dependencies.trimToSize();
+ return dependencies;
+ }
+
+ @NotNull
+ @Override
+ public List<JavaSourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex, BuildDataPaths dataPaths) {
+ List<JavaSourceRootDescriptor> roots = new ArrayList<JavaSourceRootDescriptor>();
+ JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+ Iterable<ExcludedJavaSourceRootProvider> excludedRootProviders = JpsServiceManager.getInstance().getExtensions(ExcludedJavaSourceRootProvider.class);
+ final Set<File> moduleExcludes = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ moduleExcludes.addAll(index.getModuleExcludes(myModule));
+
+ roots_loop:
+ for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
+ for (ExcludedJavaSourceRootProvider provider : excludedRootProviders) {
+ if (provider.isExcludedFromCompilation(myModule, sourceRoot) || JpsPathUtil.isUnder(moduleExcludes, sourceRoot.getFile())) {
+ continue roots_loop;
+ }
+ }
+ final String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
+ roots.add(new JavaSourceRootDescriptor(sourceRoot.getFile(), this, false, false, packagePrefix, computeRootExcludes(sourceRoot.getFile(), index)));
+ }
+ return roots;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Module '" + getModule().getName() + "' " + (myTargetType.isTests() ? "tests" : "production");
+ }
+
+ @Override
+ public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+ final JpsModule module = getModule();
+
+ int fingerprint = getDependenciesFingerprint();
+
+ final LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(module);
+ if (level != null) {
+ fingerprint += level.name().hashCode();
+ }
+
+ final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(module.getProject());
+ final String bytecodeTarget = config.getByteCodeTargetLevel(module.getName());
+ if (bytecodeTarget != null) {
+ fingerprint += bytecodeTarget.hashCode();
+ }
+
+ out.write(Integer.toHexString(fingerprint));
+ }
+
+ private int getDependenciesFingerprint() {
+ final JpsModule module = getModule();
+
+ int fingerprint = 0;
+
+ JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(module).compileOnly();
+ if (!isTests()) {
+ enumerator = enumerator.productionOnly();
+ }
+
+ for (String url : enumerator.classes().getUrls()) {
+ fingerprint = 31 * fingerprint + url.hashCode();
+ }
+ return fingerprint;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
new file mode 100644
index 000000000000..07095333470c
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Use {@link BuilderService} to register implementations of this class
+ *
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public abstract class ModuleLevelBuilder extends Builder {
+ private final BuilderCategory myCategory;
+
+ protected ModuleLevelBuilder(BuilderCategory category) {
+ myCategory = category;
+ }
+
+ public enum ExitCode {
+ NOTHING_DONE, OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED
+ }
+
+ public interface OutputConsumer {
+
+ void registerOutputFile(BuildTarget<?> target, File outputFile, Collection<String> sourcePaths) throws IOException;
+
+ void registerCompiledClass(BuildTarget<?> target, CompiledClass compiled) throws IOException;
+
+ Collection<CompiledClass> getTargetCompiledClasses(BuildTarget<?> target);
+ @NotNull
+ Map<String, CompiledClass> getCompiledClasses();
+
+ @Nullable
+ BinaryContent lookupClassBytes(String className);
+ }
+
+ public abstract ExitCode build(CompileContext context,
+ ModuleChunk chunk,
+ DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
+ OutputConsumer outputConsumer)
+ throws ProjectBuildException, IOException;
+
+ public boolean shouldHonorFileEncodingForCompilation(File file) {
+ return false;
+ }
+
+ public final BuilderCategory getCategory() {
+ return myCategory;
+ }
+
+ public void chunkBuildStarted(CompileContext context, ModuleChunk chunk) {
+ }
+
+ public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuildException.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuildException.java
new file mode 100644
index 000000000000..dd727a4176a6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuildException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+/**
+ * Use this exception to signal that the build must be stopped
+ * If Throwable cause of the stop is provided, the reason is assumed to be an unexpected internal error,
+ * so the corresponding error message "internal error" with stacktrace is additionally reported
+ *
+ * If no Throwable cause is provided, it is assumed that all the errors were reported by the builder previously and the build is just stopped
+ * Optional message, if provided, is reported as a progress message.
+ */
+public class ProjectBuildException extends Exception{
+ public ProjectBuildException() {
+ }
+
+ public ProjectBuildException(String message) {
+ super(message);
+ }
+
+ public ProjectBuildException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ProjectBuildException(Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/RebuildRequestedException.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/RebuildRequestedException.java
new file mode 100644
index 000000000000..e68a368b6649
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/RebuildRequestedException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/20/11
+ */
+public class RebuildRequestedException extends ProjectBuildException{
+
+ public RebuildRequestedException(Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java
new file mode 100644
index 000000000000..100568f95d90
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/6/11
+ */
+public class ResourcePatterns {
+ public static final Key<ResourcePatterns> KEY = Key.create("_resource_patterns_");
+
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.ResourcePatterns");
+
+ private final List<Pair<Pattern, Pattern>> myCompiledPatterns = new ArrayList<Pair<Pattern, Pattern>>();
+ private final List<Pair<Pattern, Pattern>> myNegatedCompiledPatterns = new ArrayList<Pair<Pattern, Pattern>>();
+
+ public ResourcePatterns(JpsProject project) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ final List<String> patterns = configuration.getResourcePatterns();
+ for (String pattern : patterns) {
+ final Pair<Pattern, Pattern> regexp = convertToRegexp(pattern);
+ if (isPatternNegated(pattern)) {
+ myNegatedCompiledPatterns.add(regexp);
+ }
+ else {
+ myCompiledPatterns.add(regexp);
+ }
+ }
+ }
+
+ public boolean isResourceFile(File file, @NotNull final File srcRoot) {
+ final String name = file.getName();
+ final String relativePathToParent;
+ final String parentPath = file.getParent();
+ if (parentPath != null) {
+ relativePathToParent = "/" + FileUtil.getRelativePath(FileUtil.toSystemIndependentName(srcRoot.getAbsolutePath()),
+ FileUtil.toSystemIndependentName(parentPath), '/', SystemInfo.isFileSystemCaseSensitive);
+ }
+ else {
+ relativePathToParent = null;
+ }
+ for (Pair<Pattern, Pattern> pair : myCompiledPatterns) {
+ if (matches(name, relativePathToParent, pair)) {
+ return true;
+ }
+ }
+
+ if (myNegatedCompiledPatterns.isEmpty()) {
+ return false;
+ }
+
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < myNegatedCompiledPatterns.size(); i++) {
+ if (matches(name, relativePathToParent, myNegatedCompiledPatterns.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean matches(String name, String parentRelativePath, Pair<Pattern, Pattern> nameDirPatternPair) {
+ if (!matches(name, nameDirPatternPair.getFirst())) {
+ return false;
+ }
+ final Pattern dirPattern = nameDirPatternPair.getSecond();
+ if (dirPattern == null || parentRelativePath == null) {
+ return true;
+ }
+ return matches(parentRelativePath, dirPattern);
+ }
+
+ private boolean matches(String s, Pattern p) {
+ try {
+ return p.matcher(s).matches();
+ }
+ catch (Exception e) {
+ LOG.error("Exception matching file name \"" + s + "\" against the pattern \"" + p + "\"", e);
+ return false;
+ }
+ }
+
+ private static Pair<Pattern, Pattern> convertToRegexp(String wildcardPattern) {
+ if (isPatternNegated(wildcardPattern)) {
+ wildcardPattern = wildcardPattern.substring(1);
+ }
+
+ wildcardPattern = FileUtil.toSystemIndependentName(wildcardPattern);
+
+ String dirPattern = null;
+ int slash = wildcardPattern.lastIndexOf('/');
+ if (slash >= 0) {
+ dirPattern = wildcardPattern.substring(0, slash + 1);
+ wildcardPattern = wildcardPattern.substring(slash + 1);
+ if (!dirPattern.startsWith("/")) {
+ dirPattern = "/" + dirPattern;
+ }
+ //now dirPattern starts and ends with '/'
+
+ dirPattern = normalizeWildcards(dirPattern);
+
+ dirPattern = StringUtil.replace(dirPattern, "/.*.*/", "(/.*)?/");
+ dirPattern = StringUtil.trimEnd(dirPattern, "/");
+
+ dirPattern = optimize(dirPattern);
+ }
+
+ wildcardPattern = normalizeWildcards(wildcardPattern);
+ wildcardPattern = optimize(wildcardPattern);
+
+ final Pattern dirCompiled = dirPattern == null ? null : compilePattern(dirPattern);
+ return Pair.create(compilePattern(wildcardPattern), dirCompiled);
+ }
+
+ private static String optimize(String wildcardPattern) {
+ return wildcardPattern.replaceAll("(?:\\.\\*)+", ".*");
+ }
+
+ private static String normalizeWildcards(String wildcardPattern) {
+ wildcardPattern = StringUtil.replace(wildcardPattern, "\\!", "!");
+ wildcardPattern = StringUtil.replace(wildcardPattern, ".", "\\.");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "*?", ".+");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "?*", ".+");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "*", ".*");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "?", ".");
+ return wildcardPattern;
+ }
+
+ public static boolean isPatternNegated(String wildcardPattern) {
+ return wildcardPattern.length() > 1 && wildcardPattern.charAt(0) == '!';
+ }
+
+ private static Pattern compilePattern(@NonNls String s) {
+ return Pattern.compile(s, SystemInfo.isFileSystemCaseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
new file mode 100644
index 000000000000..13ee713b2617
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.SmartList;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetRegistry;
+import org.jetbrains.jps.builders.TargetOutputIndex;
+import org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider;
+import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public final class ResourcesTarget extends JVMModuleBuildTarget<ResourceRootDescriptor> {
+ private final ResourcesTargetType myTargetType;
+
+ public ResourcesTarget(@NotNull JpsModule module, ResourcesTargetType targetType) {
+ super(targetType, module);
+ myTargetType = targetType;
+ }
+
+ @Nullable
+ public File getOutputDir() {
+ return JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, myTargetType.isTests());
+ }
+
+ @NotNull
+ @Override
+ public Collection<File> getOutputRoots(CompileContext context) {
+ Collection<File> result = new SmartList<File>();
+ final File outputDir = getOutputDir();
+ if (outputDir != null) {
+ result.add(outputDir);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isTests() {
+ return myTargetType.isTests();
+ }
+
+ @Override
+ public boolean isCompiledBeforeModuleLevelBuilders() {
+ return true;
+ }
+
+ @Override
+ public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ @Override
+ public List<ResourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex, BuildDataPaths dataPaths) {
+ List<ResourceRootDescriptor> roots = new ArrayList<ResourceRootDescriptor>();
+ JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+ Iterable<ExcludedJavaSourceRootProvider> excludedRootProviders = JpsServiceManager.getInstance().getExtensions(ExcludedJavaSourceRootProvider.class);
+
+ final THashSet<File> addedRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+ roots_loop:
+ for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
+ for (ExcludedJavaSourceRootProvider provider : excludedRootProviders) {
+ if (provider.isExcludedFromCompilation(myModule, sourceRoot)) {
+ continue roots_loop;
+ }
+ }
+ final String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
+ final File rootFile = sourceRoot.getFile();
+ roots.add(new ResourceRootDescriptor(rootFile, this, false, packagePrefix, computeRootExcludes(rootFile, index)));
+ addedRoots.add(rootFile);
+ }
+
+ return roots;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Resources for '" + getModule().getName() + "' " + (myTargetType.isTests() ? "tests" : "production");
+ }
+
+ @Override
+ public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+ final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(getModule().getProject());
+ int fingerprint = 0;
+ final List<String> patterns = config.getResourcePatterns();
+ for (String pattern : patterns) {
+ fingerprint += pattern.hashCode();
+ }
+ final List<ResourceRootDescriptor> roots = buildRootIndex.getTargetRoots(this, null);
+ for (ResourceRootDescriptor root : roots) {
+ fingerprint += FileUtil.fileHashCode(root.getRootFile());
+ fingerprint += root.getPackagePrefix().hashCode();
+ }
+ out.write(Integer.toHexString(fingerprint));
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java
new file mode 100644
index 000000000000..27609d7a5f88
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.*;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Use {@link BuilderService} to register implementations of this class
+ * @author nik
+ */
+public abstract class TargetBuilder<R extends BuildRootDescriptor, T extends BuildTarget<R>> extends Builder {
+ private final Collection<? extends BuildTargetType<? extends T>> myTargetTypes;
+
+ protected TargetBuilder(Collection<? extends BuildTargetType<? extends T>> targetTypes) {
+ myTargetTypes = targetTypes;
+ }
+
+ public Collection<? extends BuildTargetType<? extends T>> getTargetTypes() {
+ return myTargetTypes;
+ }
+
+ public abstract void build(@NotNull T target, @NotNull DirtyFilesHolder<R, T> holder, @NotNull BuildOutputConsumer outputConsumer,
+ @NotNull CompileContext context) throws ProjectBuildException, IOException;
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java
new file mode 100644
index 000000000000..32bfab619171
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsProjectLoader;
+import org.jetbrains.jps.model.serialization.PathMacroUtil;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/20/11
+ */
+public class Utils {
+ public static final Key<Map<BuildTarget<?>, Collection<String>>> REMOVED_SOURCES_KEY = Key.create("_removed_sources_");
+ public static final Key<Boolean> PROCEED_ON_ERROR_KEY = Key.create("_proceed_on_error_");
+ public static final Key<Boolean> ERRORS_DETECTED_KEY = Key.create("_errors_detected_");
+ private static volatile File ourSystemRoot = new File(System.getProperty("user.home"), ".idea-build");
+ public static final boolean IS_TEST_MODE = Boolean.parseBoolean(System.getProperty("test.mode", "false"));
+ public static final boolean IS_PROFILING_MODE = Boolean.parseBoolean(System.getProperty("profiling.mode", "false"));
+
+ private Utils() {
+ }
+
+ public static File getSystemRoot() {
+ return ourSystemRoot;
+ }
+
+ public static void setSystemRoot(File systemRoot) {
+ ourSystemRoot = systemRoot;
+ }
+
+ @Nullable
+ public static File getDataStorageRoot(String projectPath) {
+ return getDataStorageRoot(ourSystemRoot, projectPath);
+ }
+
+ public static File getDataStorageRoot(final File systemRoot, String projectPath) {
+ projectPath = FileUtil.toCanonicalPath(projectPath);
+ if (projectPath == null) {
+ return null;
+ }
+
+ String name;
+ final int locationHash;
+
+ final File rootFile = new File(projectPath);
+ if (!rootFile.isDirectory() && projectPath.endsWith(".ipr")) {
+ name = StringUtil.trimEnd(rootFile.getName(), ".ipr");
+ locationHash = projectPath.hashCode();
+ }
+ else {
+ File directoryBased = null;
+ if (PathMacroUtil.DIRECTORY_STORE_NAME.equals(rootFile.getName())) {
+ directoryBased = rootFile;
+ }
+ else {
+ File child = new File(rootFile, PathMacroUtil.DIRECTORY_STORE_NAME);
+ if (child.exists()) {
+ directoryBased = child;
+ }
+ }
+ if (directoryBased == null) {
+ return null;
+ }
+ name = JpsProjectLoader.getDirectoryBaseProjectName(directoryBased);
+ locationHash = directoryBased.getPath().hashCode();
+ }
+
+ return new File(systemRoot, name.toLowerCase(Locale.US) + "_" + Integer.toHexString(locationHash));
+ }
+
+
+ public static URI toURI(String localPath) {
+ return toURI(localPath, true);
+ }
+
+ private static URI toURI(String localPath, boolean convertSpaces) {
+ try {
+ String p = FileUtil.toSystemIndependentName(localPath);
+ if (!p.startsWith("/")) {
+ p = "/" + p;
+ }
+ if (p.startsWith("//")) {
+ p = "//" + p;
+ }
+ return new URI("file", null, convertSpaces? p.replaceAll(" ", "%20") : p, null);
+ }
+ catch (URISyntaxException e) {
+ throw new Error(e);
+ }
+ }
+
+ @Nullable
+ public static File convertToFile(final URI uri) {
+ if (uri == null) {
+ return null;
+ }
+ final String path = uri.getPath();
+ if (path == null) {
+ return null;
+ }
+ return new File(toURI(path, false));
+ }
+
+ public static boolean intersects(Set<JpsModule> set1, Set<JpsModule> set2) {
+ if (set1.size() < set2.size()) {
+ return new HashSet<JpsModule>(set1).removeAll(set2);
+ }
+ return new HashSet<JpsModule>(set2).removeAll(set1);
+ }
+
+ public static boolean errorsDetected(CompileContext context) {
+ return ERRORS_DETECTED_KEY.get(context, Boolean.FALSE);
+ }
+
+ public static String formatDuration(long duration) {
+ final long minutes = duration / 60000;
+ final long seconds = ((duration + 500L) % 60000) / 1000;
+ if (minutes > 0L) {
+ return minutes + " min " + seconds + " sec";
+ }
+ return seconds + " sec";
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
new file mode 100644
index 000000000000..44a91bd1314b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry;
+import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactUtil;
+import org.jetbrains.jps.incremental.artifacts.instructions.*;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class ArtifactBuildTarget extends BuildTarget<ArtifactRootDescriptor> {
+ private final JpsArtifact myArtifact;
+
+ public ArtifactBuildTarget(@NotNull JpsArtifact artifact) {
+ super(ArtifactBuildTargetType.INSTANCE);
+ myArtifact = artifact;
+ }
+
+ @Override
+ public String getId() {
+ return myArtifact.getName();
+ }
+
+ public JpsArtifact getArtifact() {
+ return myArtifact;
+ }
+
+ @Override
+ public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, final TargetOutputIndex outputIndex) {
+ final LinkedHashSet<BuildTarget<?>> dependencies = new LinkedHashSet<BuildTarget<?>>();
+ JpsArtifactUtil.processPackagingElements(myArtifact.getRootElement(), new Processor<JpsPackagingElement>() {
+ @Override
+ public boolean process(JpsPackagingElement element) {
+ if (element instanceof JpsArtifactOutputPackagingElement) {
+ JpsArtifact included = ((JpsArtifactOutputPackagingElement)element).getArtifactReference().resolve();
+ if (included != null && !included.equals(myArtifact)) {
+ if (!StringUtil.isEmpty(included.getOutputPath())) {
+ dependencies.add(new ArtifactBuildTarget(included));
+ return false;
+ }
+ }
+ }
+ dependencies.addAll(LayoutElementBuildersRegistry.getInstance().getDependencies(element, outputIndex));
+ return true;
+ }
+ });
+ if (!dependencies.isEmpty()) {
+ final List<BuildTarget<?>> additional = new SmartList<BuildTarget<?>>();
+ for (BuildTarget<?> dependency : dependencies) {
+ if (dependency instanceof ModuleBasedTarget<?>) {
+ final ModuleBasedTarget target = (ModuleBasedTarget)dependency;
+ additional.addAll(targetRegistry.getModuleBasedTargets(target.getModule(), target.isTests()? BuildTargetRegistry.ModuleTargetSelector.TEST : BuildTargetRegistry.ModuleTargetSelector.PRODUCTION));
+ }
+ }
+ dependencies.addAll(additional);
+ }
+ return dependencies;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ return myArtifact.equals(((ArtifactBuildTarget)o).myArtifact);
+ }
+
+ @Override
+ public int hashCode() {
+ return myArtifact.hashCode();
+ }
+
+ @Override
+ public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+ out.println(StringUtil.notNullize(myArtifact.getOutputPath()));
+ for (ArtifactRootDescriptor descriptor : buildRootIndex.getTargetRoots(this, null)) {
+ descriptor.writeConfiguration(out);
+ }
+ }
+
+ @NotNull
+ @Override
+ public List<ArtifactRootDescriptor> computeRootDescriptors(JpsModel model,
+ ModuleExcludeIndex index,
+ IgnoredFileIndex ignoredFileIndex,
+ BuildDataPaths dataPaths) {
+ ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(index, ignoredFileIndex, this);
+ ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(model, dataPaths);
+ String outputPath = StringUtil.notNullize(myArtifact.getOutputPath());
+ final CopyToDirectoryInstructionCreator instructionCreator = new CopyToDirectoryInstructionCreator(builder, outputPath);
+ LayoutElementBuildersRegistry.getInstance().generateInstructions(myArtifact, instructionCreator, context);
+ return builder.getDescriptors();
+ }
+
+ @Override
+ public ArtifactRootDescriptor findRootDescriptor(String rootId,
+ BuildRootIndex rootIndex) {
+ return rootIndex.getTargetRoots(this, null).get(Integer.valueOf(rootId));
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Artifact '" + myArtifact.getName() + "'";
+ }
+
+ @NotNull
+ @Override
+ public Collection<File> getOutputRoots(CompileContext context) {
+ String outputFilePath = myArtifact.getOutputFilePath();
+ return outputFilePath != null && !StringUtil.isEmpty(outputFilePath) ? Collections.singleton(new File(FileUtil.toSystemDependentName(outputFilePath))) : Collections.<File>emptyList();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTargetType.java
new file mode 100644
index 000000000000..4772065a814a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTargetType.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class ArtifactBuildTargetType extends BuildTargetType<ArtifactBuildTarget> {
+ public static final ArtifactBuildTargetType INSTANCE = new ArtifactBuildTargetType();
+
+ public ArtifactBuildTargetType() {
+ super("artifact");
+ }
+
+ @NotNull
+ @Override
+ public List<ArtifactBuildTarget> computeAllTargets(@NotNull JpsModel model) {
+ Collection<JpsArtifact> artifacts = JpsBuilderArtifactService.getInstance().getArtifacts(model, true);
+ List<ArtifactBuildTarget> targets = new ArrayList<ArtifactBuildTarget>(artifacts.size());
+ for (JpsArtifact artifact : artifacts) {
+ if (!StringUtil.isEmpty(artifact.getOutputPath())) {
+ targets.add(new ArtifactBuildTarget(artifact));
+ }
+ }
+ return targets;
+ }
+
+ @NotNull
+ @Override
+ public Loader createLoader(@NotNull JpsModel model) {
+ return new Loader(model);
+ }
+
+ private static class Loader extends BuildTargetLoader<ArtifactBuildTarget> {
+ private final Map<String, JpsArtifact> myArtifacts;
+
+ public Loader(JpsModel model) {
+ myArtifacts = new HashMap<String, JpsArtifact>();
+ for (JpsArtifact artifact : JpsBuilderArtifactService.getInstance().getArtifacts(model, true)) {
+ myArtifacts.put(artifact.getName(), artifact);
+ }
+ }
+
+ @Nullable
+ @Override
+ public ArtifactBuildTarget createTarget(@NotNull String targetId) {
+ JpsArtifact artifact = myArtifacts.get(targetId);
+ return artifact != null ? new ArtifactBuildTarget(artifact) : null;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java
new file mode 100644
index 000000000000..ebd30dde2769
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.incremental.BuilderService;
+import org.jetbrains.jps.incremental.TargetBuilder;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class ArtifactBuilderService extends BuilderService {
+ @Override
+ public List<? extends BuildTargetType<?>> getTargetTypes() {
+ return Collections.singletonList(ArtifactBuildTargetType.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public List<? extends TargetBuilder<?,?>> createBuilders() {
+ return Collections.singletonList(new IncArtifactBuilder());
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
new file mode 100644
index 000000000000..067a383acf40
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.util.SmartList;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.IOUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.jps.incremental.storage.AbstractStateStorage;
+import org.jetbrains.jps.incremental.storage.PathStringDescriptor;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * Stores source paths for each output path. If a source file or an output file is located in a jar file the path to the jar file is stored.
+ *
+ * @author nik
+ */
+public class ArtifactOutputToSourceMapping extends AbstractStateStorage<String, List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex>> {
+ public ArtifactOutputToSourceMapping(@NonNls File storePath) throws IOException {
+ super(storePath, new PathStringDescriptor(), new SourcePathListExternalizer());
+ }
+
+ public static class SourcePathAndRootIndex {
+ private final String myPath;
+ private final int myRootIndex;
+
+ public SourcePathAndRootIndex(String path, int rootIndex) {
+ myPath = path;
+ myRootIndex = rootIndex;
+ }
+
+ public String getPath() {
+ return myPath;
+ }
+
+ public int getRootIndex() {
+ return myRootIndex;
+ }
+ }
+
+ private static class SourcePathListExternalizer implements DataExternalizer<List<SourcePathAndRootIndex>> {
+ private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
+
+ @Override
+ public void save(DataOutput out, List<SourcePathAndRootIndex> value) throws IOException {
+ for (SourcePathAndRootIndex pair : value) {
+ IOUtil.writeUTFFast(myBuffer, out, pair.myPath);
+ out.writeInt(pair.getRootIndex());
+ }
+ }
+
+ @Override
+ public List<SourcePathAndRootIndex> read(DataInput in) throws IOException {
+ List<SourcePathAndRootIndex> result = new SmartList<SourcePathAndRootIndex>();
+ final DataInputStream stream = (DataInputStream)in;
+ while (stream.available() > 0) {
+ final String path = IOUtil.readUTFFast(myBuffer, stream);
+ final int index = stream.readInt();
+ result.add(new SourcePathAndRootIndex(path, index));
+ }
+ return result;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
new file mode 100644
index 000000000000..207fa138fd6d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.MultiMap;
+import gnu.trove.THashSet;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider;
+import org.jetbrains.jps.builders.artifacts.impl.ArtifactOutToSourceStorageProvider;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.artifacts.impl.ArtifactSorter;
+import org.jetbrains.jps.incremental.artifacts.impl.JarsBuilder;
+import org.jetbrains.jps.incremental.artifacts.instructions.*;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, ArtifactBuildTarget> {
+ public static final String BUILDER_NAME = "Artifacts builder";
+
+ public IncArtifactBuilder() {
+ super(Collections.singletonList(ArtifactBuildTargetType.INSTANCE));
+ }
+
+ @Override
+ public void build(@NotNull ArtifactBuildTarget target,
+ @NotNull DirtyFilesHolder<ArtifactRootDescriptor, ArtifactBuildTarget> holder,
+ @NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) throws ProjectBuildException {
+ JpsArtifact artifact = target.getArtifact();
+ String outputFilePath = artifact.getOutputFilePath();
+ if (StringUtil.isEmpty(outputFilePath)) {
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified"));
+ return;
+ }
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ final ArtifactSorter sorter = new ArtifactSorter(pd.getModel());
+ final Map<JpsArtifact, JpsArtifact> selfIncludingNameMap = sorter.getArtifactToSelfIncludingNameMap();
+ final JpsArtifact selfIncluding = selfIncludingNameMap.get(artifact);
+ if (selfIncluding != null) {
+ String name = selfIncluding.equals(artifact) ? "it" : "'" + selfIncluding.getName() + "' artifact";
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: " + name + " includes itself in the output layout"));
+ return;
+ }
+
+
+ try {
+ final Collection<String> deletedFiles = holder.getRemovedFiles(target);
+
+ context.processMessage(new ProgressMessage("Building artifact '" + artifact.getName() + "'..."));
+ runArtifactTasks(context, target.getArtifact(), ArtifactBuildTaskProvider.ArtifactBuildPhase.PRE_PROCESSING);
+ final SourceToOutputMapping srcOutMapping = pd.dataManager.getSourceToOutputMap(target);
+ final ArtifactOutputToSourceMapping outSrcMapping = pd.dataManager.getStorage(target, ArtifactOutToSourceStorageProvider.INSTANCE);
+
+ final TIntObjectHashMap<Set<String>> filesToProcess = new TIntObjectHashMap<Set<String>>();
+ final MultiMap<String, String> filesToDelete = new MultiMap<String, String>();
+ for (String sourcePath : deletedFiles) {
+ final Collection<String> outputPaths = srcOutMapping.getOutputs(sourcePath);
+ if (outputPaths != null) {
+ for (String outputPath : outputPaths) {
+ filesToDelete.putValue(outputPath, sourcePath);
+ final List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(outputPath);
+ if (sources != null) {
+ for (ArtifactOutputToSourceMapping.SourcePathAndRootIndex source : sources) {
+ addFileToProcess(filesToProcess, source.getRootIndex(), source.getPath(), deletedFiles);
+ }
+ }
+ }
+ }
+ }
+
+ final Set<String> changedOutputPaths = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
+ holder.processDirtyFiles(new FileProcessor<ArtifactRootDescriptor, ArtifactBuildTarget>() {
+ @Override
+ public boolean apply(ArtifactBuildTarget target, File file, ArtifactRootDescriptor root) throws IOException {
+ int rootIndex = root.getRootIndex();
+ String sourcePath = FileUtil.toSystemIndependentName(file.getPath());
+ addFileToProcess(filesToProcess, rootIndex, sourcePath, deletedFiles);
+ final Collection<String> outputPaths = srcOutMapping.getOutputs(sourcePath);
+ if (outputPaths != null) {
+ changedOutputPaths.addAll(outputPaths);
+ for (String outputPath : outputPaths) {
+ filesToDelete.putValue(outputPath, sourcePath);
+ final List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(outputPath);
+ if (sources != null) {
+ for (ArtifactOutputToSourceMapping.SourcePathAndRootIndex source : sources) {
+ addFileToProcess(filesToProcess, source.getRootIndex(), source.getPath(), deletedFiles);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ });
+
+ BuildOperations.cleanOutputsCorrespondingToChangedFiles(context, holder);
+ for (String outputPath : changedOutputPaths) {
+ outSrcMapping.remove(outputPath);
+ }
+ if (filesToDelete.isEmpty() && filesToProcess.isEmpty()) {
+ return;
+ }
+
+ deleteOutdatedFiles(filesToDelete, context, srcOutMapping, outSrcMapping);
+ context.checkCanceled();
+
+ final Set<JarInfo> changedJars = new THashSet<JarInfo>();
+ for (ArtifactRootDescriptor descriptor : pd.getBuildRootIndex().getTargetRoots(target, context)) {
+ context.checkCanceled();
+ final Set<String> sourcePaths = filesToProcess.get(descriptor.getRootIndex());
+ if (sourcePaths == null) continue;
+
+ for (String sourcePath : sourcePaths) {
+ DestinationInfo destination = descriptor.getDestinationInfo();
+ if (destination instanceof ExplodedDestinationInfo) {
+ descriptor.copyFromRoot(sourcePath, descriptor.getRootIndex(), destination.getOutputPath(), context,
+ outputConsumer, outSrcMapping);
+ }
+ else {
+ List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(destination.getOutputFilePath());
+ if (sources == null || sources.size() > 0 && sources.get(0).getRootIndex() == descriptor.getRootIndex()) {
+ outSrcMapping.update(destination.getOutputFilePath(),
+ Collections.<ArtifactOutputToSourceMapping.SourcePathAndRootIndex>emptyList());
+ changedJars.add(((JarDestinationInfo)destination).getJarInfo());
+ }
+ }
+ }
+ }
+ context.checkCanceled();
+
+ JarsBuilder builder = new JarsBuilder(changedJars, context, outputConsumer, outSrcMapping);
+ builder.buildJars();
+ runArtifactTasks(context, artifact, ArtifactBuildTaskProvider.ArtifactBuildPhase.POST_PROCESSING);
+ }
+ catch (IOException e) {
+ throw new ProjectBuildException(e);
+ }
+ }
+
+ private static void runArtifactTasks(CompileContext context, JpsArtifact artifact, ArtifactBuildTaskProvider.ArtifactBuildPhase phase)
+ throws ProjectBuildException {
+ for (ArtifactBuildTaskProvider provider : JpsServiceManager.getInstance().getExtensions(ArtifactBuildTaskProvider.class)) {
+ List<? extends BuildTask> tasks = provider.createArtifactBuildTasks(artifact, phase);
+ for (BuildTask task : tasks) {
+ task.build(context);
+ }
+ }
+ }
+
+ private static void addFileToProcess(TIntObjectHashMap<Set<String>> filesToProcess,
+ final int rootIndex,
+ final String path,
+ Collection<String> deletedFiles) {
+ if (deletedFiles.contains(path)) {
+ return;
+ }
+ Set<String> paths = filesToProcess.get(rootIndex);
+ if (paths == null) {
+ paths = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ filesToProcess.put(rootIndex, paths);
+ }
+ paths.add(path);
+ }
+
+ private static void deleteOutdatedFiles(MultiMap<String, String> filesToDelete, CompileContext context,
+ SourceToOutputMapping srcOutMapping,
+ ArtifactOutputToSourceMapping outSrcMapping) throws IOException {
+ if (filesToDelete.isEmpty()) return;
+
+ context.processMessage(new ProgressMessage("Deleting outdated files..."));
+ int notDeletedFilesCount = 0;
+ final THashSet<String> notDeletedPaths = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ final THashSet<String> deletedPaths = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+
+ for (String filePath : filesToDelete.keySet()) {
+ if (notDeletedPaths.contains(filePath)) {
+ continue;
+ }
+
+ boolean deleted = deletedPaths.contains(filePath);
+ if (!deleted) {
+ deleted = FileUtil.delete(new File(FileUtil.toSystemDependentName(filePath)));
+ }
+
+ if (deleted) {
+ outSrcMapping.remove(filePath);
+ deletedPaths.add(filePath);
+ for (String sourcePath : filesToDelete.get(filePath)) {
+ srcOutMapping.removeOutput(sourcePath, filePath);
+ }
+ }
+ else {
+ notDeletedPaths.add(filePath);
+ if (notDeletedFilesCount++ > 50) {
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.WARNING, "Deletion of outdated files stopped because too many files cannot be deleted"));
+ break;
+ }
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.WARNING, "Cannot delete file '" + filePath + "'"));
+ }
+ }
+ ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ logger.logDeletedFiles(deletedPaths);
+ }
+ }
+
+ @Override
+ public void buildStarted(final CompileContext context) {
+ //todo[nik] move to common place
+ context.addBuildListener(new BuildListener() {
+ @Override
+ public void filesGenerated(Collection<Pair<String, String>> paths) {
+ BuildFSState fsState = context.getProjectDescriptor().fsState;
+ BuildRootIndex rootsIndex = context.getProjectDescriptor().getBuildRootIndex();
+ for (Pair<String, String> pair : paths) {
+ String relativePath = pair.getSecond();
+ File file = relativePath.equals(".") ? new File(pair.getFirst()) : new File(pair.getFirst(), relativePath);
+ Collection<BuildRootDescriptor> descriptors = rootsIndex.findAllParentDescriptors(file, null, context);
+ for (BuildRootDescriptor descriptor : descriptors) {
+ try {
+ fsState.markDirty(context, file, descriptor, context.getProjectDescriptor().timestamps.getStorage(), false);
+ }
+ catch (IOException ignored) {
+ }
+ }
+ }
+ }
+
+ @Override
+ public void filesDeleted(Collection<String> paths) {
+ BuildFSState state = context.getProjectDescriptor().fsState;
+ BuildRootIndex rootsIndex = context.getProjectDescriptor().getBuildRootIndex();
+ for (String path : paths) {
+ File file = new File(FileUtil.toSystemDependentName(path));
+ Collection<BuildRootDescriptor> descriptors = rootsIndex.findAllParentDescriptors(file, null, context);
+ for (BuildRootDescriptor descriptor : descriptors) {
+ state.registerDeleted(descriptor.getTarget(), file);
+ }
+ }
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return BUILDER_NAME;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JarPathUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JarPathUtil.java
new file mode 100644
index 000000000000..c86635e5ffa1
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JarPathUtil.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JarPathUtil {
+ public static final String JAR_SEPARATOR = "!/";
+
+ @NotNull
+ public static File getLocalFile(@NotNull String fullPath) {
+ final int i = fullPath.indexOf(JAR_SEPARATOR);
+ String filePath = i == -1 ? fullPath : fullPath.substring(0, i);
+ return new File(FileUtil.toSystemDependentName(filePath));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java
new file mode 100644
index 000000000000..75c843c2270e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import org.jetbrains.jps.incremental.artifacts.impl.JpsBuilderArtifactServiceImpl;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public abstract class JpsBuilderArtifactService {
+ private static JpsBuilderArtifactService ourInstance = new JpsBuilderArtifactServiceImpl();
+
+ public static JpsBuilderArtifactService getInstance() {
+ return ourInstance;
+ }
+
+ public abstract Collection<JpsArtifact> getArtifacts(JpsModel model, boolean includeSynthetic);
+
+ public abstract Collection<JpsArtifact> getSyntheticArtifacts(JpsModel model);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java
new file mode 100644
index 000000000000..441000e85e6e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsSyntheticArtifactProvider {
+ @NotNull
+ public abstract List<JpsArtifact> createArtifacts(@NotNull JpsModel model);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java
new file mode 100644
index 000000000000..04335939661d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.builders;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.TargetOutputIndex;
+import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator;
+import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author nik
+ */
+public abstract class LayoutElementBuilderService<E extends JpsPackagingElement> {
+ private final Class<E> myElementClass;
+
+ protected LayoutElementBuilderService(Class<E> elementClass) {
+ myElementClass = elementClass;
+ }
+
+ public abstract void generateInstructions(E element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext);
+
+ public Collection<? extends BuildTarget<?>> getDependencies(@NotNull E element, TargetOutputIndex outputIndex) {
+ return Collections.emptyList();
+ }
+
+ public final Class<E> getElementClass() {
+ return myElementClass;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java
new file mode 100644
index 000000000000..0d0e90f0a532
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.builders;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ClassMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.TargetOutputIndex;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator;
+import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext;
+import org.jetbrains.jps.incremental.artifacts.instructions.CopyToDirectoryInstructionCreator;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.*;
+import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement;
+import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class LayoutElementBuildersRegistry {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry");
+
+ private static class InstanceHolder {
+
+ static final LayoutElementBuildersRegistry ourInstance = new LayoutElementBuildersRegistry();
+ }
+ public static LayoutElementBuildersRegistry getInstance() {
+ return InstanceHolder.ourInstance;
+ }
+
+ private ClassMap<LayoutElementBuilderService> myBuilders;
+
+ private LayoutElementBuildersRegistry() {
+ myBuilders = new ClassMap<LayoutElementBuilderService>();
+ LayoutElementBuilderService<?>[] standardBuilders = {
+ new RootElementBuilder(), new DirectoryElementBuilder(), new ArchiveElementBuilder(), new DirectoryCopyElementBuilder(),
+ new FileCopyElementBuilder(), new ExtractedDirectoryElementBuilder(), new ModuleOutputElementBuilder(),
+ new ModuleTestOutputElementBuilder(), new ComplexElementBuilder(), new ArtifactOutputElementBuilder()
+ };
+ for (LayoutElementBuilderService<?> builder : standardBuilders) {
+ myBuilders.put(builder.getElementClass(), builder);
+ }
+ for (LayoutElementBuilderService builder : JpsServiceManager.getInstance().getExtensions(LayoutElementBuilderService.class)) {
+ myBuilders.put(builder.getElementClass(), builder);
+ }
+ }
+
+ public void generateInstructions(JpsArtifact artifact, CopyToDirectoryInstructionCreator creator, ArtifactInstructionsBuilderContext context) {
+ context.enterArtifact(artifact);
+ generateInstructions(artifact.getRootElement(), creator, context);
+ }
+
+ public Collection<BuildTarget<?>> getDependencies(JpsPackagingElement element, TargetOutputIndex outputIndex) {
+ LayoutElementBuilderService builder = getElementBuilder(element);
+ if (builder != null) {
+ //noinspection unchecked
+ return builder.getDependencies(element, outputIndex);
+ }
+ return Collections.emptyList();
+ }
+
+ private void generateInstructions(JpsPackagingElement layoutElement, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final LayoutElementBuilderService builder = getElementBuilder(layoutElement);
+ if (builder != null) {
+ //noinspection unchecked
+ builder.generateInstructions(layoutElement, instructionCreator, builderContext);
+ }
+ }
+
+ private LayoutElementBuilderService<?> getElementBuilder(JpsPackagingElement layoutElement) {
+ final LayoutElementBuilderService<?> builder = myBuilders.get(layoutElement.getClass());
+ if (builder == null) {
+ LOG.error("Builder not found for artifact output layout element of class " + layoutElement.getClass());
+ }
+ return builder;
+ }
+
+ private void generateChildrenInstructions(JpsCompositePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateInstructions(element.getChildren(), instructionCreator, builderContext);
+ }
+
+ private void generateSubstitutionInstructions(JpsComplexPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final List<JpsPackagingElement> substitution = element.getSubstitution();
+ if (substitution != null) {
+ generateInstructions(substitution, instructionCreator, builderContext);
+ }
+ }
+
+ private void generateInstructions(final List<JpsPackagingElement> elements, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ for (JpsPackagingElement child : elements) {
+ generateInstructions(child, instructionCreator, builderContext);
+ }
+ }
+
+ private static void generateModuleOutputInstructions(@Nullable String outputUrl, ArtifactCompilerInstructionCreator creator) {
+ if (outputUrl != null) {
+ creator.addDirectoryCopyInstructions(JpsPathUtil.urlToFile(outputUrl));
+ }
+ }
+
+ private class RootElementBuilder extends LayoutElementBuilderService<JpsArtifactRootElement> {
+ public RootElementBuilder() {
+ super(JpsArtifactRootElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsArtifactRootElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) {
+ generateChildrenInstructions(element, instructionCreator, builderContext);
+ }
+ }
+
+ private class DirectoryElementBuilder extends LayoutElementBuilderService<JpsDirectoryPackagingElement> {
+ public DirectoryElementBuilder() {
+ super(JpsDirectoryPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsDirectoryPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateChildrenInstructions(element, instructionCreator.subFolder(element.getDirectoryName()), builderContext);
+ }
+ }
+
+ private class ArchiveElementBuilder extends LayoutElementBuilderService<JpsArchivePackagingElement> {
+ public ArchiveElementBuilder() {
+ super(JpsArchivePackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsArchivePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateChildrenInstructions(element, instructionCreator.archive(element.getArchiveName()), builderContext);
+ }
+ }
+
+ private static class DirectoryCopyElementBuilder extends LayoutElementBuilderService<JpsDirectoryCopyPackagingElement> {
+ public DirectoryCopyElementBuilder() {
+ super(JpsDirectoryCopyPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsDirectoryCopyPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final String dirPath = element.getDirectoryPath();
+ if (dirPath != null) {
+ final File directory = new File(dirPath);
+ instructionCreator.addDirectoryCopyInstructions(directory);
+ }
+ }
+
+ @Override
+ public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsDirectoryCopyPackagingElement element,
+ TargetOutputIndex outputIndex) {
+ String dirPath = element.getDirectoryPath();
+ if (dirPath != null) {
+ return outputIndex.getTargetsByOutputFile(new File(dirPath));
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ private static class FileCopyElementBuilder extends LayoutElementBuilderService<JpsFileCopyPackagingElement> {
+ public FileCopyElementBuilder() {
+ super(JpsFileCopyPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsFileCopyPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final String filePath = element.getFilePath();
+ if (filePath != null) {
+ final File file = new File(filePath);
+ final String fileName = element.getRenamedOutputFileName();
+ instructionCreator.addFileCopyInstruction(file, fileName != null ? fileName : file.getName());
+ }
+ }
+
+ @Override
+ public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsFileCopyPackagingElement element,
+ TargetOutputIndex outputIndex) {
+ String filePath = element.getFilePath();
+ if (filePath != null) {
+ return outputIndex.getTargetsByOutputFile(new File(filePath));
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ private static class ExtractedDirectoryElementBuilder extends LayoutElementBuilderService<JpsExtractedDirectoryPackagingElement> {
+ public ExtractedDirectoryElementBuilder() {
+ super(JpsExtractedDirectoryPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsExtractedDirectoryPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final String jarPath = element.getFilePath();
+ final String pathInJar = element.getPathInJar();
+ instructionCreator.addExtractDirectoryInstruction(new File(jarPath), pathInJar);
+ }
+ }
+
+ private static class ModuleOutputElementBuilder extends LayoutElementBuilderService<JpsProductionModuleOutputPackagingElement> {
+ public ModuleOutputElementBuilder() {
+ super(JpsProductionModuleOutputPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsProductionModuleOutputPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator);
+ }
+
+ @Override
+ public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsProductionModuleOutputPackagingElement element,
+ TargetOutputIndex outputIndex) {
+ JpsModule module = element.getModuleReference().resolve();
+ if (module != null) {
+ return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION));
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService<JpsTestModuleOutputPackagingElement> {
+ public ModuleTestOutputElementBuilder() {
+ super(JpsTestModuleOutputPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsTestModuleOutputPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator);
+ }
+
+ @Override
+ public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsTestModuleOutputPackagingElement element,
+ TargetOutputIndex outputIndex) {
+ JpsModule module = element.getModuleReference().resolve();
+ if (module != null) {
+ return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST));
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ private class ComplexElementBuilder extends LayoutElementBuilderService<JpsComplexPackagingElement> {
+ public ComplexElementBuilder() {
+ super(JpsComplexPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsComplexPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ generateSubstitutionInstructions(element, instructionCreator, builderContext);
+ }
+ }
+
+ private class ArtifactOutputElementBuilder extends LayoutElementBuilderService<JpsArtifactOutputPackagingElement> {
+ public ArtifactOutputElementBuilder() {
+ super(JpsArtifactOutputPackagingElement.class);
+ }
+
+ @Override
+ public void generateInstructions(JpsArtifactOutputPackagingElement element,
+ ArtifactCompilerInstructionCreator instructionCreator,
+ ArtifactInstructionsBuilderContext builderContext) {
+ final JpsArtifact artifact = element.getArtifactReference().resolve();
+ if (artifact == null) return;
+
+ final String outputPath = artifact.getOutputPath();
+ if (StringUtil.isEmpty(outputPath)) {
+ try {
+ if (builderContext.enterArtifact(artifact)) {
+ generateSubstitutionInstructions(element, instructionCreator, builderContext);
+ }
+ }
+ finally {
+ builderContext.leaveArtifact(artifact);
+ }
+ return;
+ }
+
+ final JpsPackagingElement rootElement = artifact.getRootElement();
+ final File outputDir = new File(outputPath);
+ if (rootElement instanceof JpsArchivePackagingElement) {
+ final String fileName = ((JpsArchivePackagingElement)rootElement).getArchiveName();
+ instructionCreator.addFileCopyInstruction(new File(outputDir, fileName), fileName);
+ }
+ else {
+ instructionCreator.addDirectoryCopyInstructions(outputDir);
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java
new file mode 100644
index 000000000000..80aad694db23
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.Processor;
+import com.intellij.util.graph.CachingSemiGraph;
+import com.intellij.util.graph.DFSTBuilder;
+import com.intellij.util.graph.GraphGenerator;
+import gnu.trove.TIntArrayList;
+import gnu.trove.TIntProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class ArtifactSorter {
+ private final JpsModel myModel;
+ private Map<JpsArtifact, JpsArtifact> myArtifactToSelfIncludingName;
+ private List<JpsArtifact> mySortedArtifacts;
+
+ public ArtifactSorter(JpsModel model) {
+ myModel = model;
+ }
+
+ public Map<JpsArtifact, JpsArtifact> getArtifactToSelfIncludingNameMap() {
+ if (myArtifactToSelfIncludingName == null) {
+ myArtifactToSelfIncludingName = computeArtifactToSelfIncludingNameMap();
+ }
+ return myArtifactToSelfIncludingName;
+ }
+
+ public List<JpsArtifact> getArtifactsSortedByInclusion() {
+ if (mySortedArtifacts == null) {
+ mySortedArtifacts = doGetSortedArtifacts();
+ }
+ return mySortedArtifacts;
+ }
+
+ private List<JpsArtifact> doGetSortedArtifacts() {
+ GraphGenerator<JpsArtifact> graph = createArtifactsGraph();
+ DFSTBuilder<JpsArtifact> builder = new DFSTBuilder<JpsArtifact>(graph);
+ builder.buildDFST();
+ List<JpsArtifact> names = new ArrayList<JpsArtifact>();
+ names.addAll(graph.getNodes());
+ Collections.sort(names, builder.comparator());
+ return names;
+ }
+
+ private Map<JpsArtifact, JpsArtifact> computeArtifactToSelfIncludingNameMap() {
+ final Map<JpsArtifact, JpsArtifact> result = new HashMap<JpsArtifact, JpsArtifact>();
+ final GraphGenerator<JpsArtifact> graph = createArtifactsGraph();
+ for (JpsArtifact artifact : graph.getNodes()) {
+ final Iterator<JpsArtifact> in = graph.getIn(artifact);
+ while (in.hasNext()) {
+ JpsArtifact next = in.next();
+ if (next.equals(artifact)) {
+ result.put(artifact, artifact);
+ break;
+ }
+ }
+ }
+
+ final DFSTBuilder<JpsArtifact> builder = new DFSTBuilder<JpsArtifact>(graph);
+ builder.buildDFST();
+ if (builder.isAcyclic() && result.isEmpty()) return Collections.emptyMap();
+
+ final TIntArrayList sccs = builder.getSCCs();
+ sccs.forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ if (size > 1) {
+ for (int j = 0; j < size; j++) {
+ final JpsArtifact artifact = builder.getNodeByTNumber(myTNumber + j);
+ result.put(artifact, artifact);
+ }
+ }
+ myTNumber += size;
+ return true;
+ }
+ });
+
+ for (int i = 0; i < graph.getNodes().size(); i++) {
+ final JpsArtifact artifact = builder.getNodeByTNumber(i);
+ if (!result.containsKey(artifact)) {
+ final Iterator<JpsArtifact> in = graph.getIn(artifact);
+ while (in.hasNext()) {
+ final JpsArtifact next = result.get(in.next());
+ if (next != null) {
+ result.put(artifact, next);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @NotNull
+ public static Set<JpsArtifact> addIncludedArtifacts(@NotNull Collection<JpsArtifact> artifacts) {
+ Set<JpsArtifact> result = new HashSet<JpsArtifact>();
+ for (JpsArtifact artifact : artifacts) {
+ collectIncludedArtifacts(artifact, new HashSet<JpsArtifact>(), result, true);
+ }
+ return result;
+ }
+
+ private static void collectIncludedArtifacts(JpsArtifact artifact,
+ final Set<JpsArtifact> processed,
+ final Set<JpsArtifact> result,
+ final boolean withOutputPathOnly) {
+ if (!processed.add(artifact)) {
+ return;
+ }
+ if (!withOutputPathOnly || !StringUtil.isEmpty(artifact.getOutputPath())) {
+ result.add(artifact);
+ }
+
+ processIncludedArtifacts(artifact, new Consumer<JpsArtifact>() {
+ @Override
+ public void consume(JpsArtifact included) {
+ collectIncludedArtifacts(included, processed, result, withOutputPathOnly);
+ }
+ });
+ }
+
+ private GraphGenerator<JpsArtifact> createArtifactsGraph() {
+ return GraphGenerator.create(CachingSemiGraph.create(new ArtifactsGraph(myModel)));
+ }
+
+ private static void processIncludedArtifacts(JpsArtifact artifact, final Consumer<JpsArtifact> consumer) {
+ JpsArtifactUtil.processPackagingElements(artifact.getRootElement(), new Processor<JpsPackagingElement>() {
+ @Override
+ public boolean process(JpsPackagingElement element) {
+ if (element instanceof JpsArtifactOutputPackagingElement) {
+ JpsArtifact included = ((JpsArtifactOutputPackagingElement)element).getArtifactReference().resolve();
+ if (included != null) {
+ consumer.consume(included);
+ }
+ return false;
+ }
+ return true;
+ }
+ });
+ }
+
+ private static class ArtifactsGraph implements GraphGenerator.SemiGraph<JpsArtifact> {
+ private final Set<JpsArtifact> myArtifactNodes;
+
+ public ArtifactsGraph(final JpsModel model) {
+ myArtifactNodes = new LinkedHashSet<JpsArtifact>(JpsBuilderArtifactService.getInstance().getArtifacts(model, true));
+ }
+
+ @Override
+ public Collection<JpsArtifact> getNodes() {
+ return myArtifactNodes;
+ }
+
+ @Override
+ public Iterator<JpsArtifact> getIn(JpsArtifact artifact) {
+ final Set<JpsArtifact> included = new LinkedHashSet<JpsArtifact>();
+ final Consumer<JpsArtifact> consumer = new Consumer<JpsArtifact>() {
+ @Override
+ public void consume(JpsArtifact artifact) {
+ if (myArtifactNodes.contains(artifact)) {
+ included.add(artifact);
+ }
+ }
+ };
+ processIncludedArtifacts(artifact, consumer);
+ return included.iterator();
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/DependentJarsEvaluator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/DependentJarsEvaluator.java
new file mode 100644
index 000000000000..046229a6287a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/DependentJarsEvaluator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.jps.incremental.artifacts.instructions.DestinationInfo;
+import org.jetbrains.jps.incremental.artifacts.instructions.JarDestinationInfo;
+import org.jetbrains.jps.incremental.artifacts.instructions.JarInfo;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class DependentJarsEvaluator {
+ private final Set<JarInfo> myJars = new LinkedHashSet<JarInfo>();
+
+ public void addJarWithDependencies(final JarInfo jarInfo) {
+ if (myJars.add(jarInfo)) {
+ final DestinationInfo destination = jarInfo.getDestination();
+ if (destination instanceof JarDestinationInfo) {
+ addJarWithDependencies(((JarDestinationInfo)destination).getJarInfo());
+ }
+ for (Pair<String, Object> pair : jarInfo.getContent()) {
+ if (pair.getSecond() instanceof JarInfo) {
+ addJarWithDependencies((JarInfo)pair.getSecond());
+ }
+ }
+ }
+ }
+
+ public Set<JarInfo> getJars() {
+ return myJars;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java
new file mode 100644
index 000000000000..2916a6b6b903
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileSystemUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.graph.CachingSemiGraph;
+import com.intellij.util.graph.DFSTBuilder;
+import com.intellij.util.graph.GraphGenerator;
+import com.intellij.util.io.ZipUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
+import org.jetbrains.jps.incremental.artifacts.IncArtifactBuilder;
+import org.jetbrains.jps.incremental.artifacts.instructions.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * @author nik
+ */
+public class JarsBuilder {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.packagingCompiler.JarsBuilder");
+ private final Set<JarInfo> myJarsToBuild;
+ private final CompileContext myContext;
+ private Map<JarInfo, File> myBuiltJars;
+ private final BuildOutputConsumer myOutputConsumer;
+ private final ArtifactOutputToSourceMapping myOutSrcMapping;
+
+ public JarsBuilder(Set<JarInfo> jarsToBuild, CompileContext context, BuildOutputConsumer outputConsumer,
+ ArtifactOutputToSourceMapping outSrcMapping) {
+ myOutputConsumer = outputConsumer;
+ myOutSrcMapping = outSrcMapping;
+ DependentJarsEvaluator evaluator = new DependentJarsEvaluator();
+ for (JarInfo jarInfo : jarsToBuild) {
+ evaluator.addJarWithDependencies(jarInfo);
+ }
+ myJarsToBuild = evaluator.getJars();
+ myContext = context;
+ }
+
+ public boolean buildJars() throws IOException, ProjectBuildException {
+ myContext.processMessage(new ProgressMessage("Building archives..."));
+
+ final JarInfo[] sortedJars = sortJars();
+ if (sortedJars == null) {
+ return false;
+ }
+
+ myBuiltJars = new HashMap<JarInfo, File>();
+ try {
+ for (JarInfo jar : sortedJars) {
+ myContext.checkCanceled();
+ buildJar(jar);
+ }
+
+ myContext.processMessage(new ProgressMessage("Copying archives..."));
+ copyJars();
+ }
+ finally {
+ deleteTemporaryJars();
+ }
+
+
+ return true;
+ }
+
+ private void deleteTemporaryJars() {
+ for (File file : myBuiltJars.values()) {
+ FileUtil.delete(file);
+ }
+ }
+
+ private void copyJars() throws IOException {
+ for (Map.Entry<JarInfo, File> entry : myBuiltJars.entrySet()) {
+ File fromFile = entry.getValue();
+ final JarInfo jarInfo = entry.getKey();
+ DestinationInfo destination = jarInfo.getDestination();
+ if (destination instanceof ExplodedDestinationInfo) {
+ File toFile = new File(FileUtil.toSystemDependentName(destination.getOutputPath()));
+ FileUtil.rename(fromFile, toFile);
+ }
+ }
+ }
+
+ @Nullable
+ private JarInfo[] sortJars() {
+ final DFSTBuilder<JarInfo> builder = new DFSTBuilder<JarInfo>(GraphGenerator.create(CachingSemiGraph.create(new JarsGraph())));
+ if (!builder.isAcyclic()) {
+ final Pair<JarInfo, JarInfo> dependency = builder.getCircularDependency();
+ String message = "Cannot build: circular dependency found between '" + dependency.getFirst().getPresentableDestination() +
+ "' and '" + dependency.getSecond().getPresentableDestination() + "'";
+ myContext.processMessage(new CompilerMessage(IncArtifactBuilder.BUILDER_NAME, BuildMessage.Kind.ERROR, message));
+ return null;
+ }
+
+ JarInfo[] jars = myJarsToBuild.toArray(new JarInfo[myJarsToBuild.size()]);
+ Arrays.sort(jars, builder.comparator());
+ jars = ArrayUtil.reverseArray(jars);
+ return jars;
+ }
+
+ private void buildJar(final JarInfo jar) throws IOException {
+ final String emptyArchiveMessage = "Archive '" + jar.getPresentableDestination() + "' doesn't contain files so it won't be created";
+ if (jar.getContent().isEmpty()) {
+ myContext.processMessage(new CompilerMessage(IncArtifactBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING, emptyArchiveMessage));
+ return;
+ }
+
+ myContext.processMessage(new ProgressMessage("Building " + jar.getPresentableDestination() + "..."));
+ File jarFile = FileUtil.createTempFile("artifactCompiler", "tmp");
+ myBuiltJars.put(jar, jarFile);
+
+ FileUtil.createParentDirs(jarFile);
+ final String targetJarPath = jar.getDestination().getOutputFilePath();
+ List<String> packedFilePaths = new ArrayList<String>();
+ Manifest manifest = loadManifest(jar, packedFilePaths);
+ final JarOutputStream jarOutputStream = createJarOutputStream(jarFile, manifest);
+
+ final THashSet<String> writtenPaths = new THashSet<String>();
+ try {
+ if (manifest != null) {
+ writtenPaths.add(JarFile.MANIFEST_NAME);
+ }
+
+ for (Pair<String, Object> pair : jar.getContent()) {
+ final String relativePath = pair.getFirst();
+ if (pair.getSecond() instanceof ArtifactRootDescriptor) {
+ final ArtifactRootDescriptor descriptor = (ArtifactRootDescriptor)pair.getSecond();
+ final int rootIndex = descriptor.getRootIndex();
+ if (descriptor instanceof FileBasedArtifactRootDescriptor) {
+ addFileToJar(jarOutputStream, jarFile, descriptor.getRootFile(), descriptor.getFilter(), relativePath, targetJarPath, writtenPaths,
+ packedFilePaths, rootIndex);
+ }
+ else {
+ final String filePath = FileUtil.toSystemIndependentName(descriptor.getRootFile().getAbsolutePath());
+ packedFilePaths.add(filePath);
+ myOutSrcMapping.appendData(targetJarPath, Collections
+ .singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ extractFileAndAddToJar(jarOutputStream, (JarBasedArtifactRootDescriptor)descriptor, relativePath, writtenPaths);
+ }
+ }
+ else {
+ JarInfo nestedJar = (JarInfo)pair.getSecond();
+ File nestedJarFile = myBuiltJars.get(nestedJar);
+ if (nestedJarFile != null) {
+ addFileToJar(jarOutputStream, jarFile, nestedJarFile, SourceFileFilter.ALL, relativePath, targetJarPath, writtenPaths,
+ packedFilePaths, -1);
+ }
+ else {
+ LOG.debug("nested jar file " + relativePath + " for " + jar.getPresentableDestination() + " not found");
+ }
+ }
+ }
+
+ if (writtenPaths.isEmpty()) {
+ myContext.processMessage(new CompilerMessage(IncArtifactBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING, emptyArchiveMessage));
+ return;
+ }
+
+ final ProjectBuilderLogger logger = myContext.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ logger.logCompiledPaths(packedFilePaths, IncArtifactBuilder.BUILDER_NAME, "Packing files:");
+ }
+ myOutputConsumer.registerOutputFile(new File(targetJarPath), packedFilePaths);
+
+ }
+ finally {
+ if (writtenPaths.isEmpty()) {
+ try {
+ jarOutputStream.close();
+ }
+ catch (IOException ignored) {
+ }
+ FileUtil.delete(jarFile);
+ myBuiltJars.remove(jar);
+ }
+ else {
+ jarOutputStream.close();
+ }
+ }
+ }
+
+ private static JarOutputStream createJarOutputStream(File jarFile, @Nullable Manifest manifest) throws IOException {
+ final BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(jarFile));
+ if (manifest != null) {
+ return new JarOutputStream(outputStream, manifest);
+ }
+ return new JarOutputStream(outputStream);
+ }
+
+ @Nullable
+ private Manifest loadManifest(JarInfo jar, List<String> packedFilePaths) throws IOException {
+ for (Pair<String, Object> pair : jar.getContent()) {
+ if (pair.getSecond() instanceof ArtifactRootDescriptor) {
+ final String rootPath = pair.getFirst();
+ if (!JarFile.MANIFEST_NAME.startsWith(rootPath)) {
+ continue;
+ }
+ final String manifestPath = JpsArtifactPathUtil.trimForwardSlashes(JarFile.MANIFEST_NAME.substring(rootPath.length()));
+ final ArtifactRootDescriptor descriptor = (ArtifactRootDescriptor)pair.getSecond();
+ if (descriptor instanceof FileBasedArtifactRootDescriptor) {
+ final File manifestFile = new File(descriptor.getRootFile(), manifestPath);
+ if (manifestFile.exists()) {
+ final String fullManifestPath = FileUtil.toSystemIndependentName(manifestFile.getAbsolutePath());
+ packedFilePaths.add(fullManifestPath);
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ return createManifest(new FileInputStream(manifestFile), manifestFile);
+ }
+ }
+ else {
+ final Ref<Manifest> manifestRef = Ref.create(null);
+ ((JarBasedArtifactRootDescriptor)descriptor).processEntries(new JarBasedArtifactRootDescriptor.EntryProcessor() {
+ @Override
+ public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException {
+ if (manifestRef.isNull() && relativePath.equals(manifestPath) && inputStream != null) {
+ manifestRef.set(createManifest(inputStream, descriptor.getRootFile()));
+ }
+ }
+ });
+ if (!manifestRef.isNull()) {
+ return manifestRef.get();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private Manifest createManifest(InputStream manifestStream, File manifestFile) {
+ try {
+ try {
+ return new Manifest(manifestStream);
+ }
+ finally {
+ manifestStream.close();
+ }
+ }
+ catch (IOException e) {
+ myContext.processMessage(new CompilerMessage(IncArtifactBuilder.BUILDER_NAME, BuildMessage.Kind.ERROR,
+ "Cannot create MANIFEST.MF from " + manifestFile.getAbsolutePath() + ":" + e.getMessage()));
+ LOG.debug(e);
+ return null;
+ }
+ }
+
+ private static void extractFileAndAddToJar(final JarOutputStream jarOutputStream, final JarBasedArtifactRootDescriptor root,
+ final String relativeOutputPath, final Set<String> writtenPaths)
+ throws IOException {
+ final long timestamp = FileSystemUtil.lastModified(root.getRootFile());
+ root.processEntries(new JarBasedArtifactRootDescriptor.EntryProcessor() {
+ @Override
+ public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException {
+ String pathInJar = addParentDirectories(jarOutputStream, writtenPaths, JpsArtifactPathUtil
+ .appendToPath(relativeOutputPath, relativePath));
+
+ if (inputStream == null) {
+ addDirectoryEntry(jarOutputStream, pathInJar + "/", writtenPaths);
+ }
+ else if (writtenPaths.add(pathInJar)) {
+ ZipEntry newEntry = new ZipEntry(pathInJar);
+ newEntry.setTime(timestamp);
+ if (entry.getMethod() == ZipEntry.STORED) {
+ newEntry.setMethod(ZipEntry.STORED);
+ newEntry.setSize(entry.getSize());
+ newEntry.setCrc(entry.getCrc());
+ }
+ jarOutputStream.putNextEntry(newEntry);
+ FileUtil.copy(inputStream, jarOutputStream);
+ jarOutputStream.closeEntry();
+ }
+ }
+ });
+
+ }
+
+ private void addFileToJar(final @NotNull JarOutputStream jarOutputStream, final @NotNull File jarFile, @NotNull File file,
+ SourceFileFilter filter, @NotNull String relativePath, String targetJarPath,
+ final @NotNull Set<String> writtenPaths, List<String> packedFilePaths, final int rootIndex) throws IOException {
+ if (!file.exists() || FileUtil.isAncestor(file, jarFile, false)) {
+ return;
+ }
+
+ relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath);
+ addFileOrDirRecursively(jarOutputStream, file, filter, relativePath, targetJarPath, writtenPaths, packedFilePaths, rootIndex);
+ }
+
+ private void addFileOrDirRecursively(@NotNull ZipOutputStream jarOutputStream,
+ @NotNull File file,
+ SourceFileFilter filter,
+ @NotNull String relativePath,
+ String targetJarPath,
+ @NotNull Set<String> writtenItemRelativePaths,
+ List<String> packedFilePaths,
+ int rootIndex) throws IOException {
+ final String filePath = FileUtil.toSystemIndependentName(file.getAbsolutePath());
+ if (!filter.accept(filePath, myContext.getProjectDescriptor())) {
+ return;
+ }
+
+ if (file.isDirectory()) {
+ final String directoryPath = relativePath.length() == 0 ? "" : relativePath + "/";
+ if (!directoryPath.isEmpty()) {
+ addDirectoryEntry(jarOutputStream, directoryPath, writtenItemRelativePaths);
+ }
+ final File[] children = file.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ addFileOrDirRecursively(jarOutputStream, child, filter, directoryPath + child.getName(), targetJarPath, writtenItemRelativePaths,
+ packedFilePaths, rootIndex);
+ }
+ }
+ return;
+ }
+
+ final boolean added = ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenItemRelativePaths, null);
+ if (rootIndex != -1) {
+ myOutSrcMapping.appendData(targetJarPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ if (added) {
+ packedFilePaths.add(filePath);
+ }
+ }
+ }
+
+
+ private static String addParentDirectories(JarOutputStream jarOutputStream, Set<String> writtenPaths, String relativePath) throws IOException {
+ while (StringUtil.startsWithChar(relativePath, '/')) {
+ relativePath = relativePath.substring(1);
+ }
+ int i = relativePath.indexOf('/');
+ while (i != -1) {
+ String prefix = relativePath.substring(0, i+1);
+ if (prefix.length() > 1) {
+ addDirectoryEntry(jarOutputStream, prefix, writtenPaths);
+ }
+ i = relativePath.indexOf('/', i + 1);
+ }
+ return relativePath;
+ }
+
+ private static void addDirectoryEntry(final ZipOutputStream output, @NonNls final String relativePath, Set<String> writtenPaths) throws IOException {
+ if (!writtenPaths.add(relativePath)) return;
+
+ ZipEntry e = new ZipEntry(relativePath);
+ e.setMethod(ZipEntry.STORED);
+ e.setSize(0);
+ e.setCrc(0);
+ output.putNextEntry(e);
+ output.closeEntry();
+ }
+
+ private class JarsGraph implements GraphGenerator.SemiGraph<JarInfo> {
+ public Collection<JarInfo> getNodes() {
+ return myJarsToBuild;
+ }
+
+ public Iterator<JarInfo> getIn(final JarInfo n) {
+ Set<JarInfo> ins = new HashSet<JarInfo>();
+ final DestinationInfo destination = n.getDestination();
+ if (destination instanceof JarDestinationInfo) {
+ ins.add(((JarDestinationInfo)destination).getJarInfo());
+ }
+ return ins.iterator();
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactPathUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactPathUtil.java
new file mode 100644
index 000000000000..9d0d2a479143
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactPathUtil.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.StringUtilRt;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactPathUtil {
+ //todo[nik] copied from DeploymentUtil
+ public static String trimForwardSlashes(@NotNull String path) {
+ while (path.length() != 0 && (path.charAt(0) == '/' || path.charAt(0) == File.separatorChar)) {
+ path = path.substring(1);
+ }
+ return path;
+ }
+
+ //todo[nik] copied from DeploymentUtil
+ public static String appendToPath(@NotNull String basePath, @NotNull String relativePath) {
+ final boolean endsWithSlash = StringUtilRt.endsWithChar(basePath, '/') || StringUtilRt.endsWithChar(basePath, '\\');
+ final boolean startsWithSlash = StringUtil.startsWithChar(relativePath, '/') || StringUtil.startsWithChar(relativePath, '\\');
+ String tail;
+ if (endsWithSlash && startsWithSlash) {
+ tail = trimForwardSlashes(relativePath);
+ }
+ else if (!endsWithSlash && !startsWithSlash && basePath.length() > 0 && relativePath.length() > 0) {
+ tail = "/" + relativePath;
+ }
+ else {
+ tail = relativePath;
+ }
+ return basePath + tail;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java
new file mode 100644
index 000000000000..f91a576366b6
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.util.Processor;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsComplexPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactUtil {
+ public static boolean processPackagingElements(@NotNull JpsPackagingElement element,
+ @NotNull Processor<JpsPackagingElement> processor) {
+ return processPackagingElements(element, processor, new HashSet<JpsPackagingElement>());
+ }
+
+ private static boolean processPackagingElements(@NotNull JpsPackagingElement element,
+ @NotNull Processor<JpsPackagingElement> processor,
+ final Set<JpsPackagingElement> processed) {
+ if (!processed.add(element)) {
+ return false;
+ }
+ if (!processor.process(element)) {
+ return false;
+ }
+
+ if (element instanceof JpsCompositePackagingElement) {
+ for (JpsPackagingElement child : ((JpsCompositePackagingElement)element).getChildren()) {
+ processPackagingElements(child, processor, processed);
+ }
+ }
+ else if (element instanceof JpsComplexPackagingElement) {
+ for (JpsPackagingElement child : ((JpsComplexPackagingElement)element).getSubstitution()) {
+ processPackagingElements(child, processor, processed);
+ }
+ }
+ return true;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java
new file mode 100644
index 000000000000..e0df6896b081
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.impl;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService;
+import org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsBuilderArtifactServiceImpl extends JpsBuilderArtifactService {
+ private static final JpsElementCollectionRole<JpsArtifact> SYNTHETIC_ARTIFACTS = JpsElementCollectionRole.create(JpsElementChildRoleBase.<JpsArtifact>create("synthetic artifact"));
+
+ @Override
+ public Collection<JpsArtifact> getArtifacts(JpsModel model, boolean includeSynthetic) {
+ List<JpsArtifact> artifacts = JpsArtifactService.getInstance().getArtifacts(model.getProject());
+ if (!includeSynthetic) {
+ return artifacts;
+ }
+ return ContainerUtil.concat(artifacts, getSyntheticArtifacts(model));
+ }
+
+ public List<JpsArtifact> getSyntheticArtifacts(final JpsModel model) {
+ JpsElementCollection<JpsArtifact> artifactsCollection = model.getProject().getContainer().getChild(SYNTHETIC_ARTIFACTS);
+ if (artifactsCollection == null) {
+ List<JpsArtifact> artifactList = computeSyntheticArtifacts(model);
+ artifactsCollection = model.getProject().getContainer().setChild(SYNTHETIC_ARTIFACTS);
+ for (JpsArtifact artifact : artifactList) {
+ artifactsCollection.addChild(artifact);
+ }
+ }
+ return artifactsCollection.getElements();
+ }
+
+ private static List<JpsArtifact> computeSyntheticArtifacts(JpsModel model) {
+ List<JpsArtifact> artifacts = new ArrayList<JpsArtifact>();
+ for (JpsSyntheticArtifactProvider provider : JpsServiceManager.getInstance().getExtensions(JpsSyntheticArtifactProvider.class)) {
+ artifacts.addAll(provider.createArtifacts(model));
+ }
+ return artifacts;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java
new file mode 100644
index 000000000000..eb2987e13e03
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface ArtifactCompilerInstructionCreator {
+
+ void addFileCopyInstruction(@NotNull File file, @NotNull String outputFileName);
+
+ void addDirectoryCopyInstructions(@NotNull File directory);
+
+ void addDirectoryCopyInstructions(@NotNull File directory, @Nullable SourceFileFilter filter);
+
+ void addExtractDirectoryInstruction(@NotNull File jarFile, @NotNull String pathInJar);
+
+ ArtifactCompilerInstructionCreator subFolder(@NotNull String directoryName);
+
+ ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName);
+
+ ArtifactCompilerInstructionCreator subFolderByRelativePath(@NotNull String relativeDirectoryPath);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
new file mode 100644
index 000000000000..89c64aefa236
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.incremental.artifacts.JarPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class ArtifactCompilerInstructionCreatorBase implements ArtifactCompilerInstructionCreator {
+ protected final ArtifactInstructionsBuilderImpl myInstructionsBuilder;
+
+ public ArtifactCompilerInstructionCreatorBase(ArtifactInstructionsBuilderImpl instructionsBuilder) {
+ myInstructionsBuilder = instructionsBuilder;
+ }
+
+ public void addDirectoryCopyInstructions(@NotNull File directoryUrl) {
+ addDirectoryCopyInstructions(directoryUrl, null);
+ }
+
+ public void addDirectoryCopyInstructions(@NotNull File directory, @Nullable SourceFileFilter filter) {
+ final boolean copyExcluded = myInstructionsBuilder.getRootsIndex().isExcluded(directory);
+ SourceFileFilter fileFilter = new SourceFileFilterImpl(filter, myInstructionsBuilder.getRootsIndex(), myInstructionsBuilder.getIgnoredFileIndex(), copyExcluded);
+ DestinationInfo destination = createDirectoryDestination();
+ if (destination != null) {
+ ArtifactRootDescriptor descriptor = myInstructionsBuilder.createFileBasedRoot(directory, fileFilter, destination);
+ if (myInstructionsBuilder.addDestination(descriptor)) {
+ onAdded(descriptor);
+ }
+ }
+ }
+
+ @Override
+ public void addExtractDirectoryInstruction(@NotNull File jarFile, @NotNull String pathInJar) {
+ //an entry of a jar file is excluded if and only if the jar file itself is excluded. In that case we should unpack entries to the artifact
+ // because the jar itself is explicitly added to the artifact layout.
+ boolean includeExcluded = true;
+
+ final SourceFileFilterImpl filter = new SourceFileFilterImpl(null, myInstructionsBuilder.getRootsIndex(),
+ myInstructionsBuilder.getIgnoredFileIndex(), includeExcluded);
+ DestinationInfo destination = createDirectoryDestination();
+ if (destination != null) {
+ ArtifactRootDescriptor descriptor = myInstructionsBuilder.createJarBasedRoot(jarFile, pathInJar, filter, destination);
+ if (myInstructionsBuilder.addDestination(descriptor)) {
+ onAdded(descriptor);
+ }
+ }
+ }
+
+ @Override
+ public abstract ArtifactCompilerInstructionCreatorBase subFolder(@NotNull String directoryName);
+
+ public ArtifactCompilerInstructionCreator subFolderByRelativePath(@NotNull String relativeDirectoryPath) {
+ final List<String> folders = StringUtil.split(relativeDirectoryPath, "/");
+ ArtifactCompilerInstructionCreator current = this;
+ for (String folder : folders) {
+ current = current.subFolder(folder);
+ }
+ return current;
+ }
+
+
+ @Override
+ public void addFileCopyInstruction(@NotNull File file, @NotNull String outputFileName) {
+ DestinationInfo destination = createFileDestination(outputFileName);
+ if (destination != null) {
+ FileBasedArtifactRootDescriptor root = myInstructionsBuilder.createFileBasedRoot(file, SourceFileFilter.ALL, destination);
+ if (myInstructionsBuilder.addDestination(root)) {
+ onAdded(root);
+ }
+ }
+ }
+
+ @Nullable
+ protected abstract DestinationInfo createDirectoryDestination();
+
+ protected abstract DestinationInfo createFileDestination(@NotNull String outputFileName);
+
+ protected abstract void onAdded(ArtifactRootDescriptor descriptor);
+
+ private static class SourceFileFilterImpl extends SourceFileFilter {
+ private final SourceFileFilter myBaseFilter;
+ private final ModuleExcludeIndex myRootsIndex;
+ private final IgnoredFileIndex myIgnoredFileIndex;
+ private final boolean myIncludeExcluded;
+
+ private SourceFileFilterImpl(@Nullable SourceFileFilter baseFilter,
+ @NotNull ModuleExcludeIndex rootsIndex,
+ IgnoredFileIndex patterns,
+ boolean includeExcluded) {
+ myBaseFilter = baseFilter;
+ myRootsIndex = rootsIndex;
+ myIgnoredFileIndex = patterns;
+ myIncludeExcluded = includeExcluded;
+ }
+
+ @Override
+ public boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException {
+ if (myBaseFilter != null && !myBaseFilter.accept(fullFilePath, projectDescriptor)) return false;
+
+ if (myIgnoredFileIndex.isIgnored(PathUtilRt.getFileName(fullFilePath))) {
+ return false;
+ }
+
+ if (!myIncludeExcluded) {
+ final File file = JarPathUtil.getLocalFile(fullFilePath);
+ if (myRootsIndex.isExcluded(file)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilder.java
new file mode 100644
index 000000000000..298ccb105ed9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilder.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface ArtifactInstructionsBuilder {
+
+ List<ArtifactRootDescriptor> getDescriptors();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java
new file mode 100644
index 000000000000..5d201f17e529
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+/**
+ * @author nik
+ */
+public interface ArtifactInstructionsBuilderContext {
+
+ boolean enterArtifact(JpsArtifact artifact);
+
+ void leaveArtifact(JpsArtifact artifact);
+
+ BuildDataPaths getDataPaths();
+
+ JpsModel getModel();
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java
new file mode 100644
index 000000000000..0d2cf4b2dc4d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class ArtifactInstructionsBuilderContextImpl implements ArtifactInstructionsBuilderContext {
+ private final Set<JpsArtifact> myParentArtifacts;
+ private final JpsModel myModel;
+ private final BuildDataPaths myDataPaths;
+
+ public ArtifactInstructionsBuilderContextImpl(JpsModel model, BuildDataPaths dataPaths) {
+ myModel = model;
+ myDataPaths = dataPaths;
+ myParentArtifacts = new HashSet<JpsArtifact>();
+ }
+
+ @Override
+ public JpsModel getModel() {
+ return myModel;
+ }
+
+ @Override
+ public BuildDataPaths getDataPaths() {
+ return myDataPaths;
+ }
+
+ @Override
+ public boolean enterArtifact(JpsArtifact artifact) {
+ return myParentArtifacts.add(artifact);
+ }
+
+ @Override
+ public void leaveArtifact(JpsArtifact artifact) {
+ myParentArtifacts.remove(artifact);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
new file mode 100644
index 000000000000..06b1bcd7eabc
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuilder {
+ private final Map<String, JarInfo> myJarByPath;
+ private final List<ArtifactRootDescriptor> myDescriptors;
+ private final ModuleExcludeIndex myRootsIndex;
+ private int myRootIndex;
+ private final IgnoredFileIndex myIgnoredFileIndex;
+ private ArtifactBuildTarget myBuildTarget;
+
+ public ArtifactInstructionsBuilderImpl(ModuleExcludeIndex rootsIndex, IgnoredFileIndex ignoredFileIndex, ArtifactBuildTarget target) {
+ myRootsIndex = rootsIndex;
+ myIgnoredFileIndex = ignoredFileIndex;
+ myBuildTarget = target;
+ myJarByPath = new HashMap<String, JarInfo>();
+ myDescriptors = new ArrayList<ArtifactRootDescriptor>();
+ }
+
+ public IgnoredFileIndex getIgnoredFileIndex() {
+ return myIgnoredFileIndex;
+ }
+
+ public boolean addDestination(@NotNull ArtifactRootDescriptor descriptor) {
+ myDescriptors.add(descriptor);
+ return true;
+ }
+
+ public ModuleExcludeIndex getRootsIndex() {
+ return myRootsIndex;
+ }
+
+ public boolean registerJarFile(@NotNull JarInfo jarInfo, @NotNull String outputPath) {
+ if (myJarByPath.containsKey(outputPath)) {
+ return false;
+ }
+ myJarByPath.put(outputPath, jarInfo);
+ return true;
+ }
+
+ @Override
+ public List<ArtifactRootDescriptor> getDescriptors() {
+ return myDescriptors;
+ }
+
+ public FileBasedArtifactRootDescriptor createFileBasedRoot(@NotNull File file,
+ @NotNull SourceFileFilter filter,
+ final DestinationInfo destinationInfo) {
+ return new FileBasedArtifactRootDescriptor(file, filter, myRootIndex++, myBuildTarget, destinationInfo);
+ }
+
+ public JarBasedArtifactRootDescriptor createJarBasedRoot(@NotNull File jarFile,
+ @NotNull String pathInJar,
+ @NotNull SourceFileFilter filter, final DestinationInfo destinationInfo) {
+ return new JarBasedArtifactRootDescriptor(jarFile, pathInJar, filter, myRootIndex, myBuildTarget, destinationInfo);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java
new file mode 100644
index 000000000000..5fe2c1c947a3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
+import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author nik
+ */
+public abstract class ArtifactRootDescriptor extends BuildRootDescriptor {
+ private static final FileFilter ALL_FILES_FILTER = new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return true;
+ }
+ };
+ protected final File myRoot;
+ private final SourceFileFilter myFilter;
+ private final int myRootIndex;
+ private final ArtifactBuildTarget myTarget;
+ private final DestinationInfo myDestinationInfo;
+
+ protected ArtifactRootDescriptor(File root,
+ @NotNull SourceFileFilter filter,
+ int index,
+ ArtifactBuildTarget target,
+ @NotNull DestinationInfo destinationInfo) {
+ myRoot = root;
+ myFilter = filter;
+ myRootIndex = index;
+ myTarget = target;
+ myDestinationInfo = destinationInfo;
+ }
+
+ public final String getArtifactName() {
+ return myTarget.getId();
+ }
+
+ @Override
+ public String toString() {
+ return getFullPath();
+ }
+
+ protected abstract String getFullPath();
+
+ public void writeConfiguration(PrintWriter out) {
+ out.println(getFullPath());
+ out.println("->" + myDestinationInfo.getOutputPath());
+ }
+
+ public ArtifactBuildTarget getTarget() {
+ return myTarget;
+ }
+
+ @Override
+ public FileFilter createFileFilter(@NotNull final ProjectDescriptor descriptor) {
+ return new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ try {
+ return myFilter.accept(pathname.getAbsolutePath(), descriptor);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ @NotNull
+ public final File getRootFile() {
+ return myRoot;
+ }
+
+ @Override
+ public String getRootId() {
+ return String.valueOf(myRootIndex);
+ }
+
+ public abstract void copyFromRoot(String filePath,
+ int rootIndex, String outputPath,
+ CompileContext context, BuildOutputConsumer outputConsumer,
+ ArtifactOutputToSourceMapping outSrcMapping) throws IOException, ProjectBuildException;
+
+ public SourceFileFilter getFilter() {
+ return myFilter;
+ }
+
+ public DestinationInfo getDestinationInfo() {
+ return myDestinationInfo;
+ }
+
+ public int getRootIndex() {
+ return myRootIndex;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootProcessor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootProcessor.java
new file mode 100644
index 000000000000..c7c8d67cff85
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootProcessor.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public interface ArtifactRootProcessor {
+ boolean process(ArtifactRootDescriptor descriptor, DestinationInfo destinations) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/CopyToDirectoryInstructionCreator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/CopyToDirectoryInstructionCreator.java
new file mode 100644
index 000000000000..f753a6b0ef59
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/CopyToDirectoryInstructionCreator.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class CopyToDirectoryInstructionCreator extends ArtifactCompilerInstructionCreatorBase {
+ private final String myOutputPath;
+
+ public CopyToDirectoryInstructionCreator(ArtifactInstructionsBuilderImpl builder, String outputPath) {
+ super(builder);
+ myOutputPath = outputPath;
+ }
+
+ protected DestinationInfo createFileDestination(@NotNull String outputFileName) {
+ return new ExplodedDestinationInfo(myOutputPath + "/" + outputFileName);
+ }
+
+ @Override
+ protected ExplodedDestinationInfo createDirectoryDestination() {
+ return new ExplodedDestinationInfo(myOutputPath);
+ }
+
+ @Override
+ protected void onAdded(ArtifactRootDescriptor descriptor) {
+ }
+
+ public CopyToDirectoryInstructionCreator subFolder(@NotNull String directoryName) {
+ return new CopyToDirectoryInstructionCreator(myInstructionsBuilder, myOutputPath + "/" + directoryName);
+ }
+
+ public ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName) {
+ String jarOutputPath = myOutputPath + "/" + archiveFileName;
+ final ExplodedDestinationInfo destination = new ExplodedDestinationInfo(jarOutputPath);
+ final JarInfo jarInfo = new JarInfo(destination);
+ if (!myInstructionsBuilder.registerJarFile(jarInfo, jarOutputPath)) {
+ return new SkipAllInstructionCreator(myInstructionsBuilder);
+ }
+ return new PackIntoArchiveInstructionCreator(myInstructionsBuilder, jarInfo, "", destination);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/DestinationInfo.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/DestinationInfo.java
new file mode 100644
index 000000000000..09f4da1cba4d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/DestinationInfo.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public abstract class DestinationInfo {
+ private final String myOutputPath;
+ private final String myOutputFilePath;
+
+ protected DestinationInfo(@NotNull final String outputPath, @NotNull String outputFilePath) {
+ myOutputPath = outputPath;
+ myOutputFilePath = outputFilePath;
+ }
+
+ @NotNull
+ public String getOutputPath() {
+ return myOutputPath;
+ }
+
+ @NotNull
+ public String getOutputFilePath() {
+ return myOutputFilePath;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ExplodedDestinationInfo.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ExplodedDestinationInfo.java
new file mode 100644
index 000000000000..b5bae0e6ad20
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ExplodedDestinationInfo.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+/**
+ * @author nik
+ */
+public class ExplodedDestinationInfo extends DestinationInfo {
+ public ExplodedDestinationInfo(final String outputPath) {
+ super(outputPath, outputPath);
+ }
+
+ public String toString() {
+ return getOutputPath();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
new file mode 100644
index 000000000000..ee42cc4da78b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
+import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
+import org.jetbrains.jps.incremental.artifacts.IncArtifactBuilder;
+import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+
+/**
+ * @author nik
+ */
+public class FileBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
+ public FileBasedArtifactRootDescriptor(@NotNull File file,
+ @NotNull SourceFileFilter filter,
+ int index,
+ ArtifactBuildTarget target,
+ @NotNull DestinationInfo destinationInfo) {
+ super(file, filter, index, target, destinationInfo);
+ }
+
+ @Override
+ protected String getFullPath() {
+ return myRoot.getPath();
+ }
+
+ public void copyFromRoot(String filePath,
+ int rootIndex, String outputPath,
+ CompileContext context, BuildOutputConsumer outputConsumer,
+ ArtifactOutputToSourceMapping outSrcMapping) throws IOException, ProjectBuildException {
+ final File file = new File(filePath);
+ if (!file.exists()) return;
+ String targetPath;
+ if (!FileUtil.filesEqual(file, getRootFile())) {
+ final String relativePath = FileUtil.getRelativePath(FileUtil.toSystemIndependentName(getRootFile().getPath()), filePath, '/');
+ if (relativePath == null || relativePath.startsWith("..")) {
+ throw new ProjectBuildException(new AssertionError(filePath + " is not under " + getRootFile().getPath()));
+ }
+ targetPath = JpsArtifactPathUtil.appendToPath(outputPath, relativePath);
+ }
+ else {
+ targetPath = outputPath;
+ }
+
+ final File targetFile = new File(targetPath);
+ if (FileUtil.filesEqual(file, targetFile)) {
+ //do not process file if should be copied to itself. Otherwise the file will be included to source-to-output mapping and will be deleted by rebuild
+ return;
+ }
+
+ if (outSrcMapping.getState(targetPath) == null) {
+ ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ logger.logCompiledFiles(Collections.singletonList(file), IncArtifactBuilder.BUILDER_NAME, "Copying file:");
+ }
+ FileUtil.copyContent(file, targetFile);
+ outputConsumer.registerOutputFile(targetFile, Collections.singletonList(filePath));
+ }
+ outSrcMapping.appendData(targetPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
new file mode 100644
index 000000000000..7c31153b7058
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
+import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
+import org.jetbrains.jps.incremental.artifacts.IncArtifactBuilder;
+import org.jetbrains.jps.incremental.artifacts.JarPathUtil;
+import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactPathUtil;
+
+import java.io.*;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * @author nik
+ */
+public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
+ private final String myPathInJar;
+
+ public JarBasedArtifactRootDescriptor(@NotNull File jarFile,
+ @NotNull String pathInJar,
+ @NotNull SourceFileFilter filter,
+ int index,
+ ArtifactBuildTarget target, DestinationInfo destinationInfo) {
+ super(jarFile, filter, index, target, destinationInfo);
+ myPathInJar = pathInJar;
+ }
+
+ public void processEntries(EntryProcessor processor) throws IOException {
+ String prefix = StringUtil.trimStart(myPathInJar, "/");
+ if (!StringUtil.endsWithChar(prefix, '/')) prefix += "/";
+ if (prefix.equals("/")) {
+ prefix = "";
+ }
+
+ ZipFile zipFile = new ZipFile(myRoot);
+ try {
+ final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ final String name = entry.getName();
+ if (name.startsWith(prefix)) {
+ String relativePath = name.substring(prefix.length());
+ processor.process(entry.isDirectory() ? null : zipFile.getInputStream(entry), relativePath, entry);
+ }
+ }
+ }
+ finally {
+ zipFile.close();
+ }
+ }
+
+ @Override
+ protected String getFullPath() {
+ return myRoot.getPath() + JarPathUtil.JAR_SEPARATOR + myPathInJar;
+ }
+
+ public void copyFromRoot(final String filePath,
+ final int rootIndex, final String outputPath,
+ CompileContext context, final BuildOutputConsumer outputConsumer,
+ final ArtifactOutputToSourceMapping outSrcMapping) throws IOException {
+ if (!myRoot.isFile()) return;
+ ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ logger.logCompiledPaths(Collections.singletonList(filePath), IncArtifactBuilder.BUILDER_NAME, "Extracting archive:");
+ }
+ processEntries(new EntryProcessor() {
+ @Override
+ public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException {
+ final String fullOutputPath = FileUtil.toSystemDependentName(JpsArtifactPathUtil.appendToPath(outputPath, relativePath));
+ final File outputFile = new File(fullOutputPath);
+
+ FileUtil.createParentDirs(outputFile);
+ if (inputStream == null) {
+ outputFile.mkdir();
+ }
+ else {
+ String fullSourcePath = filePath + JarPathUtil.JAR_SEPARATOR + relativePath;
+ if (outSrcMapping.getState(fullOutputPath) == null) {
+ final BufferedInputStream from = new BufferedInputStream(inputStream);
+ final BufferedOutputStream to = new BufferedOutputStream(new FileOutputStream(outputFile));
+ try {
+ FileUtil.copy(from, to);
+ }
+ finally {
+ from.close();
+ to.close();
+ }
+ outputConsumer.registerOutputFile(outputFile, Collections.singletonList(filePath));
+ }
+ outSrcMapping.appendData(fullOutputPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(fullSourcePath, rootIndex)));
+ }
+ }
+ });
+ }
+
+ public interface EntryProcessor {
+ void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarDestinationInfo.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarDestinationInfo.java
new file mode 100644
index 000000000000..cf7807359934
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarDestinationInfo.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+
+/**
+ * @author nik
+ */
+public class JarDestinationInfo extends DestinationInfo {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.artifacts.instructions.JarDestinationInfo");
+ private final String myPathInJar;
+ private final JarInfo myJarInfo;
+
+ public JarDestinationInfo(final String pathInJar, final JarInfo jarInfo, DestinationInfo jarDestination) {
+ super(appendPathInJar(jarDestination.getOutputPath(), pathInJar), jarDestination.getOutputFilePath());
+ LOG.assertTrue(!pathInJar.startsWith(".."), pathInJar);
+ myPathInJar = StringUtil.startsWithChar(pathInJar, '/') ? pathInJar : "/" + pathInJar;
+ myJarInfo = jarInfo;
+ }
+
+ private static String appendPathInJar(String outputPath, String pathInJar) {
+ LOG.assertTrue(outputPath.length() > 0 && outputPath.charAt(outputPath.length() - 1) != '/');
+ return outputPath + "!/" + pathInJar;
+ }
+
+ public String getPathInJar() {
+ return myPathInJar;
+ }
+
+ public JarInfo getJarInfo() {
+ return myJarInfo;
+ }
+
+ public String toString() {
+ return myPathInJar + "(" + getOutputPath() + ")";
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarInfo.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarInfo.java
new file mode 100644
index 000000000000..76b20fe5ada9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarInfo.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JarInfo {
+ private final List<Pair<String, Object>> myContent;
+ private final DestinationInfo myDestination;
+
+ public JarInfo(@NotNull DestinationInfo destination) {
+ myDestination = destination;
+ myContent = new ArrayList<Pair<String, Object>>();
+ }
+
+ public void addContent(String pathInJar, ArtifactRootDescriptor descriptor) {
+ myContent.add(Pair.create(pathInJar, (Object)descriptor));
+ }
+
+ public void addJar(String pathInJar, JarInfo jarInfo) {
+ myContent.add(Pair.create(pathInJar, (Object)jarInfo));
+ }
+
+ public List<Pair<String, Object>> getContent() {
+ return myContent;
+ }
+
+ public DestinationInfo getDestination() {
+ return myDestination;
+ }
+
+ public String getPresentableDestination() {
+ return myDestination.getOutputPath();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/PackIntoArchiveInstructionCreator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/PackIntoArchiveInstructionCreator.java
new file mode 100644
index 000000000000..3545ab5569ef
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/PackIntoArchiveInstructionCreator.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class PackIntoArchiveInstructionCreator extends ArtifactCompilerInstructionCreatorBase {
+ private final DestinationInfo myJarDestination;
+ private final JarInfo myJarInfo;
+ private final String myPathInJar;
+
+ public PackIntoArchiveInstructionCreator(ArtifactInstructionsBuilderImpl builder, JarInfo jarInfo,
+ String pathInJar, DestinationInfo jarDestination) {
+ super(builder);
+ myJarInfo = jarInfo;
+ myPathInJar = pathInJar;
+ myJarDestination = jarDestination;
+ }
+
+ @Nullable
+ @Override
+ protected DestinationInfo createDirectoryDestination() {
+ return new JarDestinationInfo(myPathInJar, myJarInfo, myJarDestination);
+ }
+
+ protected JarDestinationInfo createFileDestination(@NotNull String pathInJar) {
+ return new JarDestinationInfo(childPathInJar(pathInJar), myJarInfo, myJarDestination);
+ }
+
+ @Override
+ protected void onAdded(ArtifactRootDescriptor descriptor) {
+ myJarInfo.addContent(StringUtil.trimStart(((JarDestinationInfo)descriptor.getDestinationInfo()).getPathInJar(), "/"), descriptor);
+ }
+
+ private String childPathInJar(String fileName) {
+ return myPathInJar.length() == 0 ? fileName : myPathInJar + "/" + fileName;
+ }
+
+ public PackIntoArchiveInstructionCreator subFolder(@NotNull String directoryName) {
+ return new PackIntoArchiveInstructionCreator(myInstructionsBuilder, myJarInfo, childPathInJar(directoryName), myJarDestination);
+ }
+
+ public ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName) {
+ final JarDestinationInfo destination = createFileDestination(archiveFileName);
+ final JarInfo jarInfo = new JarInfo(destination);
+ final String outputPath = myJarDestination.getOutputPath() + "/" + archiveFileName;
+ if (!myInstructionsBuilder.registerJarFile(jarInfo, outputPath)) {
+ return new SkipAllInstructionCreator(myInstructionsBuilder);
+ }
+ myJarInfo.addJar(destination.getPathInJar(), jarInfo);
+ return new PackIntoArchiveInstructionCreator(myInstructionsBuilder, jarInfo, "", destination);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SkipAllInstructionCreator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SkipAllInstructionCreator.java
new file mode 100644
index 000000000000..234316a16efc
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SkipAllInstructionCreator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class SkipAllInstructionCreator extends ArtifactCompilerInstructionCreatorBase {
+ public SkipAllInstructionCreator(ArtifactInstructionsBuilderImpl builder) {
+ super(builder);
+ }
+
+ @Override
+ protected DestinationInfo createFileDestination(@NotNull String outputFileName) {
+ return null;
+ }
+
+ @Override
+ protected void onAdded(ArtifactRootDescriptor descriptor) {
+ }
+
+ @Override
+ protected DestinationInfo createDirectoryDestination() {
+ return null;
+ }
+
+ public SkipAllInstructionCreator subFolder(@NotNull String directoryName) {
+ return this;
+ }
+
+ public SkipAllInstructionCreator archive(@NotNull String archiveFileName) {
+ return this;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java
new file mode 100644
index 000000000000..60964afdf726
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public abstract class SourceFileFilter {
+ public static final SourceFileFilter ALL = new SourceFileFilter() {
+ @Override
+ public boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) {
+ return true;
+ }
+ };
+
+ public abstract boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java
new file mode 100644
index 000000000000..a2942a64d348
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.fs;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileSystemUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.CompileScope;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.incremental.Utils;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 12/16/11
+ */
+public class BuildFSState extends FSState {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.BuildFSState");
+ private static final Key<Set<? extends BuildTarget<?>>> CONTEXT_TARGETS_KEY = Key.create("_fssfate_context_targets_");
+ private static final Key<FilesDelta> CURRENT_ROUND_DELTA_KEY = Key.create("_current_round_delta_");
+ private static final Key<FilesDelta> LAST_ROUND_DELTA_KEY = Key.create("_last_round_delta_");
+
+ // when true, will always determine dirty files by scanning FS and comparing timestamps
+ // alternatively, when false, after first scan will rely on external notifications about changes
+ private final boolean myAlwaysScanFS;
+
+ public BuildFSState(boolean alwaysScanFS) {
+ myAlwaysScanFS = alwaysScanFS;
+ }
+
+ @Override
+ public boolean isInitialScanPerformed(BuildTarget<?> target) {
+ return !myAlwaysScanFS && super.isInitialScanPerformed(target);
+ }
+
+ @Override
+ public Map<BuildRootDescriptor, Set<File>> getSourcesToRecompile(@NotNull CompileContext context, BuildTarget<?> target) {
+ if (target instanceof ModuleBuildTarget) {
+ // multiple compilation rounds are applicable to ModuleBuildTarget only
+ final FilesDelta lastRoundDelta = getRoundDelta(LAST_ROUND_DELTA_KEY, context);
+ if (lastRoundDelta != null) {
+ return lastRoundDelta.getSourcesToRecompile();
+ }
+ }
+ return super.getSourcesToRecompile(context, target);
+ }
+
+ //public boolean isMarkedForRecompilation(BuildRootDescriptor rd, File file) {
+ // final Map<BuildRootDescriptor, Set<File>> recompile = getDelta(rd.getTarget()).getSourcesToRecompile();
+ // //noinspection SynchronizationOnLocalVariableOrMethodParameter
+ // synchronized (recompile) {
+ // final Set<File> files = recompile.get(rd);
+ // return files != null && files.contains(file);
+ // }
+ //}
+
+ @Override
+ public boolean markDirty(@Nullable CompileContext context, File file, final BuildRootDescriptor rd, @Nullable Timestamps tsStorage, boolean saveEventStamp) throws IOException {
+ final FilesDelta roundDelta = getRoundDelta(CURRENT_ROUND_DELTA_KEY, context);
+ if (roundDelta != null && isInCurrentContextTargets(context, rd)) {
+ roundDelta.markRecompile(rd, file);
+ }
+ return super.markDirty(context, file, rd, tsStorage, saveEventStamp);
+ }
+
+ private static boolean isInCurrentContextTargets(CompileContext context, BuildRootDescriptor rd) {
+ if (context == null) {
+ return false;
+ }
+ Set<? extends BuildTarget<?>> targets = CONTEXT_TARGETS_KEY.get(context, Collections.<BuildTarget<?>>emptySet());
+ return targets.contains(rd.getTarget());
+ }
+
+ @Override
+ public boolean markDirtyIfNotDeleted(@Nullable CompileContext context, File file, final BuildRootDescriptor rd, @Nullable Timestamps tsStorage) throws IOException {
+ final boolean marked = super.markDirtyIfNotDeleted(context, file, rd, tsStorage);
+ if (marked) {
+ final FilesDelta roundDelta = getRoundDelta(CURRENT_ROUND_DELTA_KEY, context);
+ if (roundDelta != null) {
+ if (isInCurrentContextTargets(context, rd)) {
+ roundDelta.markRecompile(rd, file);
+ }
+ }
+ }
+ return marked;
+ }
+
+ public void clearAll() {
+ clearContextRoundData(null);
+ clearContextChunk(null);
+ super.clearAll();
+ }
+
+ public void clearContextRoundData(@Nullable CompileContext context) {
+ setRoundDelta(CURRENT_ROUND_DELTA_KEY, context, null);
+ setRoundDelta(LAST_ROUND_DELTA_KEY, context, null);
+ }
+
+ public void clearContextChunk(@Nullable CompileContext context) {
+ setContextTargets(context, null);
+ }
+
+ public void beforeChunkBuildStart(@NotNull CompileContext context, BuildTargetChunk chunk) {
+ setContextTargets(context, chunk.getTargets());
+ }
+
+ public void beforeNextRoundStart(@NotNull CompileContext context, ModuleChunk chunk) {
+ setRoundDelta(LAST_ROUND_DELTA_KEY, context, getRoundDelta(CURRENT_ROUND_DELTA_KEY, context));
+ setRoundDelta(CURRENT_ROUND_DELTA_KEY, context, new FilesDelta());
+ }
+
+ public <R extends BuildRootDescriptor, T extends BuildTarget<R>> boolean processFilesToRecompile(CompileContext context, final T target, final FileProcessor<R, T> processor) throws IOException {
+ final Map<BuildRootDescriptor, Set<File>> data = getSourcesToRecompile(context, target);
+ BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex();
+ final CompileScope scope = context.getScope();
+ synchronized (data) {
+ for (Map.Entry<BuildRootDescriptor, Set<File>> entry : data.entrySet()) {
+ //noinspection unchecked
+ R root = (R)entry.getKey();
+ FileFilter filter = rootIndex.getRootFilter(root, context.getProjectDescriptor());
+ for (File file : entry.getValue()) {
+ if (!scope.isAffected(target, file) || !filter.accept(file)) {
+ continue;
+ }
+ if (!processor.apply(target, file, root)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return true if marked something, false otherwise
+ */
+ public boolean markAllUpToDate(CompileContext context, final BuildRootDescriptor rd, final Timestamps stamps) throws IOException {
+ boolean marked = false;
+ final FilesDelta delta = getDelta(rd.getTarget());
+ final Set<File> files = delta.clearRecompile(rd);
+ if (files != null) {
+ FileFilter filter = context.getProjectDescriptor().getBuildRootIndex().getRootFilter(rd, context.getProjectDescriptor());
+ CompileScope scope = context.getScope();
+ final long compilationStartStamp = context.getCompilationStartStamp();
+ for (File file : files) {
+ if (filter.accept(file)) {
+ if (scope.isAffected(rd.getTarget(), file)) {
+ final long currentFileStamp = FileSystemUtil.lastModified(file);
+ if (!rd.isGenerated() && (currentFileStamp > compilationStartStamp || getEventRegistrationStamp(file) > compilationStartStamp)) {
+ // if the file was modified after the compilation had started,
+ // do not save the stamp considering file dirty
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath());
+ }
+ delta.markRecompile(rd, file);
+ }
+ else {
+ marked = true;
+ stamps.saveStamp(file, rd.getTarget(), currentFileStamp);
+ }
+ }
+ else {
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath());
+ }
+ delta.markRecompile(rd, file);
+ }
+ }
+ else {
+ stamps.removeStamp(file, rd.getTarget());
+ }
+ }
+ }
+ return marked;
+ }
+
+ private static void setContextTargets(@Nullable CompileContext context, @Nullable Set<? extends BuildTarget<?>> targets) {
+ if (context != null) {
+ CONTEXT_TARGETS_KEY.set(context, targets);
+ }
+ }
+
+ @Nullable
+ private static FilesDelta getRoundDelta(@NotNull Key<FilesDelta> key, @Nullable CompileContext context) {
+ return context != null? key.get(context) : null;
+ }
+
+ private static void setRoundDelta(@NotNull Key<FilesDelta> key, @Nullable CompileContext context, @Nullable FilesDelta delta) {
+ if (context != null) {
+ key.set(context, delta);
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java
new file mode 100644
index 000000000000..462b8eaf027e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.fs;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.io.IOUtil;
+import gnu.trove.TObjectLongHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.storage.Timestamps;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 4/20/12
+ */
+public class FSState {
+ public static final int VERSION = 3;
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.FSState");
+ private final Map<BuildTarget<?>, FilesDelta> myDeltas = Collections.synchronizedMap(new HashMap<BuildTarget<?>, FilesDelta>());
+ private final Set<BuildTarget<?>> myInitialScanPerformed = Collections.synchronizedSet(new HashSet<BuildTarget<?>>());
+ private final TObjectLongHashMap<File> myRegistrationStamps = new TObjectLongHashMap<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+ public void save(DataOutput out) throws IOException {
+ MultiMap<BuildTargetType<?>, BuildTarget<?>> targetsByType = new MultiMap<BuildTargetType<?>, BuildTarget<?>>();
+ for (BuildTarget<?> target : myInitialScanPerformed) {
+ targetsByType.putValue(target.getTargetType(), target);
+ }
+ out.writeInt(targetsByType.size());
+ for (BuildTargetType<?> type : targetsByType.keySet()) {
+ IOUtil.writeString(type.getTypeId(), out);
+ Collection<BuildTarget<?>> targets = targetsByType.get(type);
+ out.writeInt(targets.size());
+ for (BuildTarget<?> target : targets) {
+ IOUtil.writeString(target.getId(), out);
+ getDelta(target).save(out);
+ }
+ }
+ }
+
+ public void load(DataInputStream in, JpsModel model, final BuildRootIndex buildRootIndex) throws IOException {
+ BuilderRegistry registry = BuilderRegistry.getInstance();
+ int typeCount = in.readInt();
+ while (typeCount-- > 0) {
+ final String typeId = IOUtil.readString(in);
+ int targetCount = in.readInt();
+ BuildTargetType<?> type = registry.getTargetType(typeId);
+ BuildTargetLoader<?> loader = type != null ? type.createLoader(model) : null;
+ while (targetCount-- > 0) {
+ final String id = IOUtil.readString(in);
+ boolean loaded = false;
+ if (loader != null) {
+ BuildTarget<?> target = loader.createTarget(id);
+ if (target != null) {
+ getDelta(target).load(in, target, buildRootIndex);
+ myInitialScanPerformed.add(target);
+ loaded = true;
+ }
+ }
+ if (!loaded) {
+ LOG.info("Skipping unknown target (typeId=" + typeId + ", type=" + type + ", id=" + id + ")");
+ FilesDelta.skip(in);
+ }
+ }
+ }
+ }
+
+ public void clearAll() {
+ myInitialScanPerformed.clear();
+ myDeltas.clear();
+ myRegistrationStamps.clear();
+ }
+
+ public final void clearRecompile(final BuildRootDescriptor rd) {
+ getDelta(rd.getTarget()).clearRecompile(rd);
+ }
+
+ public boolean markDirty(@Nullable CompileContext context, final File file, final BuildRootDescriptor rd, final @Nullable Timestamps tsStorage, boolean saveEventStamp) throws IOException {
+ final boolean marked = getDelta(rd.getTarget()).markRecompile(rd, file);
+ if (marked) {
+ if (saveEventStamp) {
+ myRegistrationStamps.put(file, System.currentTimeMillis());
+ }
+ if (tsStorage != null) {
+ tsStorage.removeStamp(file, rd.getTarget());
+ }
+ }
+ return marked;
+ }
+
+ public long getEventRegistrationStamp(File file) {
+ return myRegistrationStamps.get(file);
+ }
+
+ public boolean markDirtyIfNotDeleted(@Nullable CompileContext context,
+ final File file,
+ final BuildRootDescriptor rd,
+ final @Nullable Timestamps tsStorage) throws IOException {
+ final boolean marked = getDelta(rd.getTarget()).markRecompileIfNotDeleted(rd, file);
+ if (marked && tsStorage != null) {
+ tsStorage.removeStamp(file, rd.getTarget());
+ }
+ return marked;
+ }
+
+ public void registerDeleted(BuildTarget<?> target, final File file, @Nullable Timestamps tsStorage) throws IOException {
+ registerDeleted(target, file);
+ if (tsStorage != null) {
+ tsStorage.removeStamp(file, target);
+ }
+ }
+
+ public void registerDeleted(BuildTarget<?> target, File file) {
+ getDelta(target).addDeleted(file);
+ }
+
+ public Map<BuildRootDescriptor, Set<File>> getSourcesToRecompile(@NotNull CompileContext context, BuildTarget<?> target) {
+ return getDelta(target).getSourcesToRecompile();
+ }
+
+ public void clearDeletedPaths(BuildTarget<?> target) {
+ final FilesDelta delta = myDeltas.get(target);
+ if (delta != null) {
+ delta.clearDeletedPaths();
+ }
+ }
+
+ public Collection<String> getAndClearDeletedPaths(BuildTarget<?> target) {
+ final FilesDelta delta = myDeltas.get(target);
+ if (delta != null) {
+ return delta.getAndClearDeletedPaths();
+ }
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ protected final FilesDelta getDelta(BuildTarget<?> buildTarget) {
+ synchronized (myDeltas) {
+ FilesDelta delta = myDeltas.get(buildTarget);
+ if (delta == null) {
+ delta = new FilesDelta();
+ myDeltas.put(buildTarget, delta);
+ }
+ return delta;
+ }
+ }
+
+ public boolean hasWorkToDo(BuildTarget<?> target) {
+ if (!myInitialScanPerformed.contains(target)) return true;
+ FilesDelta delta = myDeltas.get(target);
+ return delta != null && delta.hasChanges();
+ }
+
+ public void markInitialScanPerformed(BuildTarget<?> target) {
+ myInitialScanPerformed.add(target);
+ }
+
+ public boolean isInitialScanPerformed(BuildTarget<?> target) {
+ return myInitialScanPerformed.contains(target);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java
new file mode 100644
index 000000000000..79c6ab127ea7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.fs;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.IOUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.incremental.Utils;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/
+final class FilesDelta {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.FilesDelta");
+
+ private final Set<String> myDeletedPaths = Collections.synchronizedSet(new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY));
+ private final Map<BuildRootDescriptor, Set<File>> myFilesToRecompile = Collections.synchronizedMap(new HashMap<BuildRootDescriptor, Set<File>>());
+
+ public void save(DataOutput out) throws IOException {
+ out.writeInt(myDeletedPaths.size());
+ synchronized (myDeletedPaths) {
+ for (String path : myDeletedPaths) {
+ IOUtil.writeString(path, out);
+ }
+ }
+ synchronized (myFilesToRecompile) {
+ out.writeInt(myFilesToRecompile.size());
+ for (Map.Entry<BuildRootDescriptor, Set<File>> entry : myFilesToRecompile.entrySet()) {
+ IOUtil.writeString(entry.getKey().getRootId(), out);
+ final Set<File> files = entry.getValue();
+ out.writeInt(files.size());
+ for (File file : files) {
+ IOUtil.writeString(FileUtil.toSystemIndependentName(file.getPath()), out);
+ }
+ }
+ }
+ }
+
+ public void load(DataInput in, @NotNull BuildTarget<?> target, BuildRootIndex buildRootIndex) throws IOException {
+ myDeletedPaths.clear();
+ int deletedCount = in.readInt();
+ while (deletedCount-- > 0) {
+ myDeletedPaths.add(IOUtil.readString(in));
+ }
+ myFilesToRecompile.clear();
+ int recompileCount = in.readInt();
+ while (recompileCount-- > 0) {
+ String rootId = IOUtil.readString(in);
+ BuildRootDescriptor descriptor = target.findRootDescriptor(rootId, buildRootIndex);
+ Set<File> files;
+ if (descriptor != null) {
+ files = myFilesToRecompile.get(descriptor);
+ if (files == null) {
+ files = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ myFilesToRecompile.put(descriptor, files);
+ }
+ }
+ else {
+ LOG.debug("Cannot find root by " + rootId + ", delta will be skipped");
+ files = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ }
+ int filesCount = in.readInt();
+ while (filesCount-- > 0) {
+ final File file = new File(IOUtil.readString(in));
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Loaded " + file.getPath());
+ }
+ files.add(file);
+ }
+ }
+ }
+
+ public static void skip(DataInput in) throws IOException {
+ int deletedCount = in.readInt();
+ while (deletedCount-- > 0) {
+ IOUtil.readString(in);
+ }
+ int recompiledCount = in.readInt();
+ while (recompiledCount-- > 0) {
+ IOUtil.readString(in);
+ int filesCount = in.readInt();
+ while (filesCount-- > 0) {
+ IOUtil.readString(in);
+ }
+ }
+ }
+
+ public boolean hasChanges() {
+ return hasPathsToDelete() || hasSourcesToRecompile();
+ }
+
+
+ public boolean markRecompile(BuildRootDescriptor root, File file) {
+ final boolean added = _addToRecompiled(root, file);
+ if (added) {
+ synchronized (myDeletedPaths) {
+ if (!myDeletedPaths.isEmpty()) { // optimization
+ myDeletedPaths.remove(FileUtil.toCanonicalPath(file.getPath()));
+ }
+ }
+ }
+ return added;
+ }
+
+ public boolean markRecompileIfNotDeleted(BuildRootDescriptor root, File file) {
+ final boolean isMarkedDeleted;
+ synchronized (myDeletedPaths) {
+ isMarkedDeleted = !myDeletedPaths.isEmpty() && myDeletedPaths.contains(FileUtil.toCanonicalPath(file.getPath()));
+ }
+ if (!isMarkedDeleted) {
+ return _addToRecompiled(root, file);
+ }
+ return false;
+ }
+
+ private boolean _addToRecompiled(BuildRootDescriptor root, File file) {
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Marking dirty: " + file.getPath());
+ }
+
+ Set<File> files;
+ synchronized (myFilesToRecompile) {
+ files = myFilesToRecompile.get(root);
+ if (files == null) {
+ files = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ myFilesToRecompile.put(root, files);
+ }
+ return files.add(file);
+ }
+ }
+
+ public void addDeleted(File file) {
+ // ensure the file is no more marked to recompilation
+ synchronized (myFilesToRecompile) {
+ for (Set<File> files : myFilesToRecompile.values()) {
+ files.remove(file);
+ }
+ }
+ final String path = FileUtil.toCanonicalPath(file.getPath());
+ myDeletedPaths.add(path);
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Marking deleted: " + path);
+ }
+ }
+
+ public void clearDeletedPaths() {
+ myDeletedPaths.clear();
+ }
+
+ public Set<String> getAndClearDeletedPaths() {
+ synchronized (myDeletedPaths) {
+ try {
+ final THashSet<String> _paths = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ _paths.addAll(myDeletedPaths);
+ return _paths;
+ }
+ finally {
+ myDeletedPaths.clear();
+ }
+ }
+ }
+
+ public Map<BuildRootDescriptor, Set<File>> getSourcesToRecompile() {
+ return myFilesToRecompile;
+ }
+
+ private boolean hasSourcesToRecompile() {
+ synchronized (myFilesToRecompile) {
+ if(!myFilesToRecompile.isEmpty()) {
+ for (Set<File> files : myFilesToRecompile.values()) {
+ if (!files.isEmpty()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean hasPathsToDelete() {
+ return !myDeletedPaths.isEmpty();
+ }
+
+ @Nullable
+ public Set<File> clearRecompile(BuildRootDescriptor root) {
+ return myFilesToRecompile.remove(root);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java
new file mode 100644
index 000000000000..c03ebcb800ec
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.instrumentation;
+
+import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
+import com.intellij.compiler.instrumentation.InstrumenterClassWriter;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.incremental.BinaryContent;
+import org.jetbrains.jps.incremental.BuilderCategory;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.CompiledClass;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/25/12
+ */
+public abstract class BaseInstrumentingBuilder extends ClassProcessingBuilder {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder");
+ // every instance of builder must have its own marker!
+ private final Key<Boolean> IS_INSTRUMENTED_KEY = Key.create("_instrumentation_marker_" + getPresentableName());
+
+ public BaseInstrumentingBuilder() {
+ super(BuilderCategory.CLASS_INSTRUMENTER);
+ }
+
+ @Override
+ protected final ExitCode performBuild(CompileContext context, ModuleChunk chunk, InstrumentationClassFinder finder, OutputConsumer outputConsumer) {
+ ExitCode exitCode = ExitCode.NOTHING_DONE;
+ for (CompiledClass compiledClass : outputConsumer.getCompiledClasses().values()) {
+ final BinaryContent originalContent = compiledClass.getContent();
+ final ClassReader reader = new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
+ final int version = getClassFileVersion(reader);
+ if (IS_INSTRUMENTED_KEY.get(compiledClass, Boolean.FALSE) || !canInstrument(compiledClass, version)) {
+ // do not instrument the same content twice
+ continue;
+ }
+ final ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
+ try {
+ final BinaryContent instrumented = instrument(context, compiledClass, reader, writer, finder);
+ if (instrumented != null) {
+ compiledClass.setContent(instrumented);
+ finder.cleanCachedData(compiledClass.getClassName());
+ IS_INSTRUMENTED_KEY.set(compiledClass, Boolean.TRUE);
+ exitCode = ExitCode.OK;
+ }
+ }
+ catch (Throwable e) {
+ LOG.info(e);
+ final String message = e.getMessage();
+ if (message != null) {
+ context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, message, compiledClass.getSourceFile().getPath()));
+ }
+ else {
+ context.processMessage(new CompilerMessage(getPresentableName(), e));
+ }
+ }
+ }
+ return exitCode;
+ }
+
+ protected abstract boolean canInstrument(CompiledClass compiledClass, int classFileVersion);
+
+ @Nullable
+ protected abstract BinaryContent instrument(CompileContext context,
+ CompiledClass compiled,
+ ClassReader reader,
+ ClassWriter writer,
+ InstrumentationClassFinder finder);
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
new file mode 100644
index 000000000000..8131cfd62739
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.instrumentation;
+
+import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/30/12
+ */
+public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
+ private static final Key<InstrumentationClassFinder> CLASS_FINDER = Key.create("_cached_instrumentation_class_finder_");
+
+ public ClassProcessingBuilder(BuilderCategory category) {
+ super(category);
+ }
+
+ protected abstract boolean isEnabled(CompileContext context, ModuleChunk chunk);
+
+ protected abstract String getProgressMessage();
+
+ @Override
+ public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
+ final InstrumentationClassFinder finder = CLASS_FINDER.get(context);
+ if (finder != null) {
+ CLASS_FINDER.set(context, null);
+ finder.releaseResources();
+ }
+ }
+
+ @Override
+ public final ExitCode build(CompileContext context, ModuleChunk chunk, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder, OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
+ if (outputConsumer.getCompiledClasses().isEmpty() || !isEnabled(context, chunk)) {
+ return ExitCode.NOTHING_DONE;
+ }
+
+ final String progress = getProgressMessage();
+ final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress);
+ if (shouldShowProgress) {
+ context.processMessage(new ProgressMessage(progress + " [" + chunk.getName() + "]"));
+ }
+
+ ExitCode exitCode = ExitCode.NOTHING_DONE;
+ try {
+ InstrumentationClassFinder finder = CLASS_FINDER.get(context); // try using shared finder
+ if (finder == null) {
+ final Collection<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false);
+ final Collection<File> classpath = new ArrayList<File>();
+ classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false));
+ classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());
+
+ finder = createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
+ CLASS_FINDER.set(context, finder);
+ }
+
+ exitCode = performBuild(context, chunk, finder, outputConsumer);
+ }
+ finally {
+ if (shouldShowProgress) {
+ context.processMessage(new ProgressMessage("")); // cleanup progress
+ }
+ }
+ return exitCode;
+ }
+
+ protected abstract ExitCode performBuild(CompileContext context, ModuleChunk chunk, InstrumentationClassFinder finder, OutputConsumer outputConsumer);
+
+
+ // utility methods
+ public static InstrumentationClassFinder createInstrumentationClassFinder(Collection<File> platformCp, Collection<File> cp, final OutputConsumer outputConsumer) throws
+ MalformedURLException {
+ final URL[] platformUrls = new URL[platformCp.size()];
+ int index = 0;
+ for (File file : platformCp) {
+ platformUrls[index++] = file.toURI().toURL();
+ }
+
+ final URL[] urls = new URL[cp.size()];
+ index = 0;
+ for (File file : cp) {
+ urls[index++] = file.toURI().toURL();
+ }
+
+ return new InstrumentationClassFinder(platformUrls, urls) {
+ protected InputStream lookupClassBeforeClasspath(String internalClassName) {
+ final BinaryContent content = outputConsumer.lookupClassBytes(internalClassName.replace("/", "."));
+ if (content != null) {
+ return new ByteArrayInputStream(content.getBuffer(), content.getOffset(), content.getLength());
+ }
+ return null;
+ }
+ };
+ }
+
+ public static int getAsmClassWriterFlags(int version) {
+ return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS;
+ }
+
+ public static int getClassFileVersion(ClassReader reader) {
+ final Ref<Integer> result = new Ref<Integer>(0);
+ reader.accept(new ClassVisitor(Opcodes.ASM4) {
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ result.set(version);
+ }
+ }, 0);
+ return result.get();
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java
new file mode 100644
index 000000000000..74f8280fac97
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.instrumentation;
+
+import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
+import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.BinaryContent;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.CompiledClass;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+
+import java.io.File;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/21/12
+ */
+public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{
+
+ public NotNullInstrumentingBuilder() {
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "NotNull instrumentation";
+ }
+
+ @Override
+ protected String getProgressMessage() {
+ return "Adding @NotNull assertions...";
+ }
+
+ @Override
+ protected boolean isEnabled(CompileContext context, ModuleChunk chunk) {
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+ return JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).isAddNotNullAssertions();
+ }
+
+ @Override
+ protected boolean canInstrument(CompiledClass compiledClass, int classFileVersion) {
+ return classFileVersion >= Opcodes.V1_5;
+ }
+
+ // todo: probably instrument other NotNull-like annotations defined in project settings?
+ @Override
+ @Nullable
+ protected BinaryContent instrument(CompileContext context,
+ CompiledClass compiledClass,
+ ClassReader reader,
+ ClassWriter writer,
+ InstrumentationClassFinder finder) {
+ try {
+ final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer);
+ reader.accept(instrumenter, 0);
+ if (instrumenter.isModification()) {
+ return new BinaryContent(writer.toByteArray());
+ }
+ }
+ catch (Throwable e) {
+ final StringBuilder msg = new StringBuilder();
+ msg.append("@NotNull instrumentation failed ");
+ final File sourceFile = compiledClass.getSourceFile();
+ msg.append(" for ").append(sourceFile.getName());
+ msg.append(": ").append(e.getMessage());
+ context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, msg.toString(), sourceFile.getPath()));
+ }
+ return null;
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/RmiStubsGenerator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/RmiStubsGenerator.java
new file mode 100644
index 000000000000..02c5cc1c1c30
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/RmiStubsGenerator.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.instrumentation;
+
+import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
+import com.intellij.execution.process.BaseOSProcessHandler;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.SystemProperties;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
+import org.jetbrains.jps.model.java.compiler.RmicCompilerOptions;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.File;
+import java.io.IOException;
+import java.rmi.Remote;
+import java.util.*;
+import java.util.concurrent.Future;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 11/30/12
+ */
+public class RmiStubsGenerator extends ClassProcessingBuilder {
+ private static final String REMOTE_INTERFACE_NAME = Remote.class.getName().replace('.', '/');
+ private static final File[] EMPTY_FILE_ARRAY = new File[0];
+ private static Key<Boolean> IS_ENABLED = Key.create("_rmic_compiler_enabled_");
+
+ public RmiStubsGenerator() {
+ super(BuilderCategory.CLASS_INSTRUMENTER);
+ }
+
+ @Override
+ protected String getProgressMessage() {
+ return "Generating RMI stubs...";
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "rmic";
+ }
+
+ @Override
+ public void buildStarted(CompileContext context) {
+ super.buildStarted(context);
+ final RmicCompilerOptions rmicOptions = getOptions(context);
+ IS_ENABLED.set(context, rmicOptions != null && rmicOptions.IS_EANABLED);
+ }
+
+ @Override
+ protected boolean isEnabled(CompileContext context, ModuleChunk chunk) {
+ return IS_ENABLED.get(context, Boolean.FALSE);
+ }
+
+ @Override
+ protected ExitCode performBuild(CompileContext context, ModuleChunk chunk, InstrumentationClassFinder finder, OutputConsumer outputConsumer) {
+ ExitCode exitCode = ExitCode.NOTHING_DONE;
+ if (!outputConsumer.getCompiledClasses().isEmpty()) {
+ final Map<ModuleBuildTarget, Collection<ClassItem>> remoteClasses = new THashMap<ModuleBuildTarget, Collection<ClassItem>>();
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ for (CompiledClass compiledClass : outputConsumer.getTargetCompiledClasses(target)) {
+ try {
+ if (isRemote(compiledClass, finder)) {
+ Collection<ClassItem> list = remoteClasses.get(target);
+ if (list == null) {
+ list = new ArrayList<ClassItem>();
+ remoteClasses.put(target, list);
+ }
+ list.add(new ClassItem(compiledClass));
+ }
+ }
+ catch (IOException e) {
+ context.processMessage(new CompilerMessage(getPresentableName(), e));
+ }
+ }
+ }
+ if (!remoteClasses.isEmpty()) {
+ exitCode = generateRmiStubs(context, remoteClasses, chunk, outputConsumer);
+ }
+ }
+ return exitCode;
+ }
+
+ private ExitCode generateRmiStubs(final CompileContext context,
+ Map<ModuleBuildTarget, Collection<ClassItem>> remoteClasses,
+ ModuleChunk chunk,
+ OutputConsumer outputConsumer) {
+ ExitCode exitCode = ExitCode.NOTHING_DONE;
+
+ final Collection<File> classpath = ProjectPaths.getCompilationClasspath(chunk, false);
+ final StringBuilder buf = new StringBuilder();
+ for (File file : classpath) {
+ if (buf.length() > 0) {
+ buf.append(File.pathSeparator);
+ }
+ buf.append(file.getPath());
+ }
+ final String classpathString = buf.toString();
+ final String rmicPath = getPathToRmic(chunk);
+ final RmicCompilerOptions options = getOptions(context);
+ final List<ModuleBuildTarget> targetsProcessed = new ArrayList<ModuleBuildTarget>(remoteClasses.size());
+
+ for (Map.Entry<ModuleBuildTarget, Collection<ClassItem>> entry : remoteClasses.entrySet()) {
+ try {
+ final ModuleBuildTarget target = entry.getKey();
+ final Collection<String> cmdLine = createStartupCommand(
+ target, rmicPath, classpathString, options, entry.getValue()
+ );
+ final Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(cmdLine));
+ final BaseOSProcessHandler handler = new BaseOSProcessHandler(process, null, null) {
+ @Override
+ protected Future<?> executeOnPooledThread(Runnable task) {
+ return SharedThreadPool.getInstance().executeOnPooledThread(task);
+ }
+ };
+
+ final RmicOutputParser stdOutParser = new RmicOutputParser(context, getPresentableName());
+ final RmicOutputParser stdErrParser = new RmicOutputParser(context, getPresentableName());
+ handler.addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ if (outputType == ProcessOutputTypes.STDOUT) {
+ stdOutParser.append(event.getText());
+ }
+ else if (outputType == ProcessOutputTypes.STDERR) {
+ stdErrParser.append(event.getText());
+ }
+ }
+
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ super.processTerminated(event);
+ }
+ });
+ handler.startNotify();
+ handler.waitFor();
+ targetsProcessed.add(target);
+ if (stdErrParser.isErrorsReported() || stdOutParser.isErrorsReported()) {
+ break;
+ }
+ else {
+ final int exitValue = handler.getProcess().exitValue();
+ if (exitValue != 0) {
+ context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, "RMI stub generation failed"));
+ break;
+ }
+ }
+ }
+ catch (IOException e) {
+ context.processMessage(new CompilerMessage(getPresentableName(), e));
+ break;
+ }
+ }
+
+ // registering generated files
+ final Map<File, File[]> fsCache = new THashMap<File, File[]>(FileUtil.FILE_HASHING_STRATEGY);
+ for (ModuleBuildTarget target : targetsProcessed) {
+ final Collection<ClassItem> items = remoteClasses.get(target);
+ for (ClassItem item : items) {
+ File[] children = fsCache.get(item.parentDir);
+ if (children == null) {
+ children = item.parentDir.listFiles();
+ if (children == null) {
+ children = EMPTY_FILE_ARRAY;
+ }
+ fsCache.put(item.parentDir, children);
+ }
+ final Collection<File> files = item.selectGeneratedFiles(children);
+ if (!files.isEmpty()) {
+ final Collection<String> sources = Collections.singleton(item.compiledClass.getSourceFile().getPath());
+ for (File generated : files) {
+ try {
+ outputConsumer.registerOutputFile(target, generated, sources);
+ }
+ catch (IOException e) {
+ context.processMessage(new CompilerMessage(getPresentableName(), e));
+ }
+ }
+ }
+ }
+ }
+
+ return exitCode;
+ }
+
+ private static Collection<String> createStartupCommand(final ModuleBuildTarget target,
+ final String compilerPath,
+ final String classpath,
+ final RmicCompilerOptions config,
+ final Collection<ClassItem> items) {
+ final List<String> commandLine = new ArrayList<String>();
+ commandLine.add(compilerPath);
+
+ if (config.DEBUGGING_INFO) {
+ commandLine.add("-g");
+ }
+ if(config.GENERATE_IIOP_STUBS) {
+ commandLine.add("-iiop");
+ }
+ final StringTokenizer tokenizer = new StringTokenizer(config.ADDITIONAL_OPTIONS_STRING, " \t\r\n");
+ while(tokenizer.hasMoreTokens()) {
+ final String token = tokenizer.nextToken();
+ commandLine.add(token);
+ }
+
+ commandLine.add("-classpath");
+ commandLine.add(classpath);
+
+ commandLine.add("-d");
+ final File outputDir = target.getOutputDir();
+ assert outputDir != null;
+ commandLine.add(outputDir.getPath());
+
+ for (ClassItem item : items) {
+ commandLine.add(item.compiledClass.getClassName());
+ }
+ return commandLine;
+ }
+
+ private static String getPathToRmic(ModuleChunk chunk) {
+ final JpsSdk<?> sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE);
+ if (sdk != null) {
+ final String executable = JpsJavaSdkType.getJavaExecutable(sdk);
+ if (executable != null) {
+ final int idx = FileUtil.toSystemIndependentName(executable).lastIndexOf("/");
+ if (idx >= 0) {
+ return executable.substring(0, idx) + "/rmic";
+ }
+ }
+ }
+ return SystemProperties.getJavaHome() + "/bin/rmic";
+ }
+
+ private static boolean isRemote(CompiledClass compiled, InstrumentationClassFinder finder) throws IOException{
+ try {
+ final InstrumentationClassFinder.PseudoClass pseudoClass = finder.loadClass(compiled.getClassName());
+ if (pseudoClass != null && !pseudoClass.isInterface()) {
+ for (InstrumentationClassFinder.PseudoClass anInterface : pseudoClass.getInterfaces()) {
+ if (isRemoteInterface(anInterface, REMOTE_INTERFACE_NAME)) {
+ return true;
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException ignored) {
+ }
+ return false;
+ }
+
+ private static boolean isRemoteInterface(InstrumentationClassFinder.PseudoClass iface, final String remoteInterfaceName)
+ throws IOException, ClassNotFoundException {
+ if (remoteInterfaceName.equals(iface.getName())) {
+ return true;
+ }
+ for (InstrumentationClassFinder.PseudoClass superIface : iface.getInterfaces()) {
+ if (isRemoteInterface(superIface, remoteInterfaceName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ private static RmicCompilerOptions getOptions(CompileContext context) {
+ final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(context.getProjectDescriptor().getProject());
+ if (config != null) {
+ final JpsJavaCompilerOptions options = config.getCompilerOptions("Rmic");
+ if (options instanceof RmicCompilerOptions) {
+ return (RmicCompilerOptions)options;
+ }
+ }
+ return null;
+ }
+
+ private static final class ClassItem {
+ static final String[] GEN_SUFFIXES = {"_Stub.class", "_Skel.class", "_Tie.class"};
+ final CompiledClass compiledClass;
+ final File parentDir;
+ final String baseName;
+
+ ClassItem(CompiledClass compiledClass) {
+ this.compiledClass = compiledClass;
+ final File outputFile = compiledClass.getOutputFile();
+ parentDir = outputFile.getParentFile();
+ baseName = StringUtil.trimEnd(outputFile.getName(), ".class");
+ }
+
+ @NotNull
+ public Collection<File> selectGeneratedFiles(File[] candidates) {
+ if (candidates == null || candidates.length == 0) {
+ return Collections.emptyList();
+ }
+ final Collection<File> result = new SmartList<File>();
+ final String[] suffixes = new String[GEN_SUFFIXES.length];
+ for (int i = 0; i < GEN_SUFFIXES.length; i++) {
+ suffixes[i] = baseName + GEN_SUFFIXES[i];
+ }
+ for (File candidate : candidates) {
+ final String name = candidate.getName();
+ for (String suffix : suffixes) {
+ if (name.endsWith(suffix)) {
+ result.add(candidate);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ private static class RmicOutputParser extends LineOutputWriter {
+ private final CompileContext myContext;
+ private final String myCompilerName;
+ private boolean myErrorsReported = false;
+
+ private RmicOutputParser(CompileContext context, String name) {
+ myContext = context;
+ myCompilerName = name;
+ }
+
+ private boolean isErrorsReported() {
+ return myErrorsReported;
+ }
+
+ @Override
+ protected void lineAvailable(String line) {
+ if (!StringUtil.isEmpty(line)) {
+ BuildMessage.Kind kind = BuildMessage.Kind.INFO;
+ if (line.contains("error")) {
+ kind = BuildMessage.Kind.ERROR;
+ myErrorsReported = true;
+ }
+ else if (line.contains("warning")) {
+ kind = BuildMessage.Kind.WARNING;
+ }
+ myContext.processMessage(new CompilerMessage(myCompilerName, kind, line));
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/AnnotationsExcludedJavaSourceRootProvider.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/AnnotationsExcludedJavaSourceRootProvider.java
new file mode 100644
index 000000000000..4634be644d28
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/AnnotationsExcludedJavaSourceRootProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+
+import java.io.File;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 12/14/12
+ */
+public class AnnotationsExcludedJavaSourceRootProvider extends ExcludedJavaSourceRootProvider{
+ @Override
+ public boolean isExcludedFromCompilation(@NotNull JpsModule module, @NotNull JpsModuleSourceRoot root) {
+ final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(module.getProject());
+ final ProcessorConfigProfile profile = compilerConfig.getAnnotationProcessingProfile(module);
+ if (!profile.isEnabled()) {
+ return false;
+ }
+
+ final File outputDir =
+ ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir(module, JavaSourceRootType.TEST_SOURCE == root.getRootType(), profile);
+
+ return outputDir != null && FileUtil.filesEqual(outputDir, root.getFile());
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ClassPostProcessor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ClassPostProcessor.java
new file mode 100644
index 000000000000..b37b9f45ead2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ClassPostProcessor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.javac.OutputFileObject;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/21/12
+*/
+public interface ClassPostProcessor {
+ void process(CompileContext context, OutputFileObject out);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/CopyResourcesUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/CopyResourcesUtil.java
new file mode 100644
index 000000000000..b5542f38c97b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/CopyResourcesUtil.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class CopyResourcesUtil {
+ private CopyResourcesUtil() {
+ }
+
+ public static File copyClass(final String targetPath, @NonNls final String className, final boolean deleteOnExit) throws IOException{
+ final File targetDir = new File(targetPath).getAbsoluteFile();
+ final File file = new File(targetDir, className + ".class");
+ FileUtil.createParentDirs(file);
+ if (deleteOnExit) {
+ for (File f = file; f != null && !FileUtil.filesEqual(f, targetDir); f = FileUtilRt.getParentFile(f)) {
+ f.deleteOnExit();
+ }
+ }
+ @NonNls final String resourceName = "/" + className + ".class";
+ final InputStream stream = CopyResourcesUtil.class.getResourceAsStream(resourceName);
+ if (stream == null) {
+ throw new IOException("cannot load " + resourceName);
+ }
+ return copyStreamToFile(stream, file);
+ }
+
+ private static File copyStreamToFile(final InputStream stream, final File file) throws IOException {
+ try {
+ final FileOutputStream outputStream = new FileOutputStream(file);
+ try {
+ FileUtil.copy(stream, outputStream);
+ }
+ finally {
+ outputStream.close();
+ }
+ }
+ finally {
+ stream.close();
+ }
+ return file;
+ }
+
+ public static void copyProperties(final String targetPath, final String fileName) throws IOException {
+ final File targetDir = new File(targetPath).getAbsoluteFile();
+ final File file = new File(targetDir, fileName);
+ FileUtil.createParentDirs(file);
+ for (File f = file; f != null && !FileUtil.filesEqual(f, targetDir); f = FileUtilRt.getParentFile(f)) {
+ f.deleteOnExit();
+ }
+ final String resourceName = "/" + fileName;
+ final InputStream stream = CopyResourcesUtil.class.getResourceAsStream(resourceName);
+ if (stream == null) {
+ return;
+ }
+ copyStreamToFile(stream, file);
+ }
+
+ public static List<File> copyFormsRuntime(final String targetDir, final boolean deleteOnExit) throws IOException {
+ String[] runtimeClasses = {
+ "AbstractLayout",
+ "DimensionInfo",
+ "GridConstraints",
+ "GridLayoutManager",
+ "HorizontalInfo",
+ "LayoutState",
+ "Spacer",
+ "SupportCode$TextWithMnemonic",
+ "SupportCode",
+ "Util",
+ "VerticalInfo",
+ };
+
+ List<File> copied = new ArrayList<File>();
+ for (String runtimeClass : runtimeClasses) {
+ copied.add(copyClass(targetDir, "com/intellij/uiDesigner/core/" + runtimeClass, deleteOnExit));
+ }
+ return copied;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java
new file mode 100644
index 000000000000..63e468da0af4
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.execution.process.BaseOSProcessHandler;
+import com.intellij.openapi.util.Key;
+import org.jetbrains.jps.javac.JavacServerClient;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/24/12
+ */
+public class ExternalJavacDescriptor {
+ public static final Key<ExternalJavacDescriptor> KEY = Key.create("_external_javac_descriptor_");
+
+ public final BaseOSProcessHandler process;
+ public final JavacServerClient client;
+
+ public ExternalJavacDescriptor(BaseOSProcessHandler process, JavacServerClient client) {
+ this.process = process;
+ this.client = client;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/FormsParsing.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/FormsParsing.java
new file mode 100644
index 000000000000..c53d04fa04e3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/FormsParsing.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.uiDesigner.UIFormXmlConstants;
+import net.n3.nanoxml.*;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.util.Properties;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/12/11
+ */
+public class FormsParsing {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.FormsParsing");
+ private static final String FORM_TAG = "form";
+
+ private FormsParsing() {
+ }
+
+ public static String readBoundClassName(File formFile) throws IOException {
+ final BufferedInputStream in = new BufferedInputStream(new FileInputStream(formFile));
+ try {
+ final Ref<String> result = new Ref<String>(null);
+ parse(in, new IXMLBuilderAdapter() {
+ public void startElement(final String elemName, final String nsPrefix, final String nsURI, final String systemID, final int lineNr)
+ throws Exception {
+ if (!FORM_TAG.equalsIgnoreCase(elemName)) {
+ stop();
+ }
+ }
+
+ public void addAttribute(final String key, final String nsPrefix, final String nsURI, final String value, final String type)
+ throws Exception {
+ if (UIFormXmlConstants.ATTRIBUTE_BIND_TO_CLASS.equals(key)) {
+ result.set(value);
+ stop();
+ }
+ }
+
+ public void elementAttributesProcessed(final String name, final String nsPrefix, final String nsURI) throws Exception {
+ stop();
+ }
+ });
+ return result.get();
+ }
+ finally {
+ in.close();
+ }
+ }
+
+ public static void parse(final InputStream is, final IXMLBuilder builder) {
+ try {
+ parse(new MyXMLReader(is), builder);
+ }
+ catch(IOException e) {
+ LOG.error(e);
+ }
+ finally {
+
+ try {
+ is.close();
+ }
+ catch (IOException ignore) {
+
+ }
+ }
+ }
+
+ public static void parse(final IXMLReader r, final IXMLBuilder builder) {
+ try {
+ final IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
+ parser.setReader(r);
+ parser.setBuilder(builder);
+ parser.setValidator(new EmptyValidator());
+ parser.setResolver(new EmptyEntityResolver());
+ try {
+ parser.parse();
+ }
+ catch (XMLException e) {
+ if (e.getException() instanceof ParserStoppedException) {
+ return;
+ }
+ LOG.debug(e);
+ }
+ }
+ catch (ClassNotFoundException e) {
+ LOG.error(e);
+ }
+ catch (InstantiationException e) {
+ LOG.error(e);
+ }
+ catch (IllegalAccessException e) {
+ LOG.error(e);
+ }
+ }
+
+ private static class EmptyValidator extends NonValidator {
+ private IXMLEntityResolver myParameterEntityResolver;
+
+ public void setParameterEntityResolver(IXMLEntityResolver resolver) {
+ myParameterEntityResolver = resolver;
+ }
+
+ public IXMLEntityResolver getParameterEntityResolver() {
+ return myParameterEntityResolver;
+ }
+
+ public void parseDTD(String publicID, IXMLReader reader, IXMLEntityResolver entityResolver, boolean external) throws Exception {
+ if (!external) {
+ //super.parseDTD(publicID, reader, entityResolver, external);
+ int cnt = 1;
+ for (char ch = reader.read(); !(ch == ']' && --cnt == 0); ch = reader.read()) {
+ if (ch == '[') cnt ++;
+ }
+ }
+ else {
+ int origLevel = reader.getStreamLevel();
+
+ while (true) {
+ char ch = reader.read();
+
+ if (reader.getStreamLevel() < origLevel) {
+ reader.unread(ch);
+ return; // end external DTD
+ }
+ }
+ }
+ }
+
+ public void elementStarted(String name, String systemId, int lineNr) {
+ }
+
+ public void elementEnded(String name, String systemId, int lineNr) {
+ }
+
+ public void attributeAdded(String key, String value, String systemId, int lineNr) {
+ }
+
+ public void elementAttributesProcessed(String name, Properties extraAttributes, String systemId, int lineNr) {
+ }
+
+ public void PCDataAdded(String systemId, int lineNr) {
+ }
+ }
+
+ private static class EmptyEntityResolver implements IXMLEntityResolver {
+ public void addInternalEntity(String name, String value) {
+ }
+
+ public void addExternalEntity(String name, String publicID, String systemID) {
+ }
+
+ public Reader getEntity(IXMLReader xmlReader, String name) throws XMLParseException {
+ return new StringReader("");
+ }
+
+ public boolean isExternalEntity(String name) {
+ return false;
+ }
+ }
+
+ private static class MyXMLReader extends StdXMLReader {
+ private String publicId;
+ private String systemId;
+
+ public MyXMLReader(final Reader documentReader) {
+ super(documentReader);
+ }
+
+ public MyXMLReader(InputStream stream) throws IOException {
+ super(stream);
+ }
+
+ @Override
+ public Reader openStream(String publicId, String systemId) throws IOException {
+ this.publicId = StringUtil.isEmpty(publicId) ? null : publicId;
+ this.systemId = StringUtil.isEmpty(systemId) ? null : systemId;
+
+ return new StringReader(" ");
+ }
+ }
+
+ public static class IXMLBuilderAdapter implements IXMLBuilder {
+
+ public void startBuilding(final String systemID, final int lineNr) throws Exception {
+ }
+
+ public void newProcessingInstruction(final String target, final Reader reader) throws Exception {
+
+ }
+
+ public void startElement(final String name, final String nsPrefix, final String nsURI, final String systemID, final int lineNr)
+ throws Exception {
+ }
+
+ public void addAttribute(final String key, final String nsPrefix, final String nsURI, final String value, final String type)
+ throws Exception {
+ }
+
+ public void elementAttributesProcessed(final String name, final String nsPrefix, final String nsURI) throws Exception {
+ }
+
+ public void endElement(final String name, final String nsPrefix, final String nsURI) throws Exception {
+ }
+
+ public void addPCData(final Reader reader, final String systemID, final int lineNr) throws Exception {
+ }
+
+ @Nullable
+ public Object getResult() throws Exception {
+ return null;
+ }
+
+ protected static void stop() {
+ throw new ParserStoppedException();
+ }
+ }
+
+ public static class ParserStoppedException extends RuntimeException {
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
new file mode 100644
index 000000000000..b4870b523ff3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.execution.process.BaseOSProcessHandler;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SystemProperties;
+import com.intellij.util.concurrency.SequentialTaskExecutor;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.api.GlobalOptions;
+import org.jetbrains.jps.api.RequestFuture;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.builders.java.dependencyView.Mappings;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.javac.*;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.java.LanguageLevel;
+import org.jetbrains.jps.model.java.compiler.*;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import javax.tools.*;
+import java.io.*;
+import java.net.ServerSocket;
+import java.util.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/21/11
+ */
+public class JavaBuilder extends ModuleLevelBuilder {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.JavaBuilder");
+ public static final String BUILDER_NAME = "java";
+ private static final String JAVA_EXTENSION = ".java";
+ public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null;
+ private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_");
+ private static final Key<Boolean> IS_ENABLED = Key.create("_java_compiler_enabled_");
+ private static final Key<AtomicReference<String>> COMPILER_VERSION_INFO = Key.create("_java_compiler_version_info_");
+
+ private static final Set<String> FILTERED_OPTIONS = new HashSet<String>(Arrays.<String>asList(
+ "-target"
+ ));
+ private static final Set<String> FILTERED_SINGLE_OPTIONS = new HashSet<String>(Arrays.<String>asList(
+ "-g", "-deprecation", "-nowarn", "-verbose", "-proc:none", "-proc:only", "-proceedOnError"
+ ));
+
+ private static final FileFilter JAVA_SOURCES_FILTER =
+ SystemInfo.isFileSystemCaseSensitive?
+ new FileFilter() {
+ public boolean accept(File file) {
+ return file.getPath().endsWith(JAVA_EXTENSION);
+ }
+ } :
+ new FileFilter() {
+ public boolean accept(File file) {
+ return StringUtil.endsWithIgnoreCase(file.getPath(), JAVA_EXTENSION);
+ }
+ };
+
+ private final Executor myTaskRunner;
+ private static final List<ClassPostProcessor> ourClassProcessors = new ArrayList<ClassPostProcessor>();
+
+ public static void registerClassPostProcessor(ClassPostProcessor processor) {
+ ourClassProcessors.add(processor);
+ }
+
+ public JavaBuilder(Executor tasksExecutor) {
+ super(BuilderCategory.TRANSLATOR);
+ myTaskRunner = new SequentialTaskExecutor(tasksExecutor);
+ //add here class processors in the sequence they should be executed
+ }
+
+ @NotNull
+ public String getPresentableName() {
+ return BUILDER_NAME;
+ }
+
+ @Override
+ public void buildStarted(CompileContext context) {
+ final JpsProject project = context.getProjectDescriptor().getProject();
+ final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
+ final String compilerId = config == null? JavaCompilers.JAVAC_ID : config.getJavaCompilerId();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Java compiler ID: " + compilerId);
+ }
+ final boolean isJavac = JavaCompilers.JAVAC_ID.equalsIgnoreCase(compilerId) || JavaCompilers.JAVAC_API_ID.equalsIgnoreCase(compilerId);
+ final boolean isEclipse = JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
+ IS_ENABLED.set(context, isJavac || isEclipse);
+ String messageText = null;
+ if (isJavac) {
+ messageText = "Using javac " + System.getProperty("java.version") + " to compile java sources";
+ }
+ else if (isEclipse) {
+ messageText = "Using eclipse compiler to compile java sources";
+ }
+ COMPILER_VERSION_INFO.set(context, new AtomicReference<String>(messageText));
+ }
+
+ public ExitCode build(final CompileContext context,
+ final ModuleChunk chunk,
+ DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
+ OutputConsumer outputConsumer) throws ProjectBuildException {
+ if (!IS_ENABLED.get(context, Boolean.TRUE)) {
+ return ExitCode.NOTHING_DONE;
+ }
+ try {
+ final Map<File, ModuleBuildTarget> filesToCompile = new THashMap<File, ModuleBuildTarget>(FileUtil.FILE_HASHING_STRATEGY);
+
+ dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
+ public boolean apply(ModuleBuildTarget target, File file, JavaSourceRootDescriptor descriptor) throws IOException {
+ if (JAVA_SOURCES_FILTER.accept(file)) {
+ filesToCompile.put(file, target);
+ }
+ return true;
+ }
+ });
+
+ if (context.isMake()) {
+ final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+ if (logger.isEnabled()) {
+ if (filesToCompile.size() > 0) {
+ logger.logCompiledFiles(filesToCompile.keySet(), BUILDER_NAME, "Compiling files:");
+ }
+ }
+ }
+
+ return compile(context, chunk, dirtyFilesHolder, filesToCompile.keySet(), outputConsumer);
+ }
+ catch (ProjectBuildException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ String message = e.getMessage();
+ if (message == null) {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final PrintStream stream = new PrintStream(out);
+ try {
+ e.printStackTrace(stream);
+ }
+ finally {
+ stream.close();
+ }
+ message = "Internal error: \n" + out.toString();
+ }
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message));
+ throw new ProjectBuildException(message, e);
+ }
+ }
+
+ @Override
+ public boolean shouldHonorFileEncodingForCompilation(File file) {
+ return JAVA_SOURCES_FILTER.accept(file);
+ }
+
+
+ private ExitCode compile(final CompileContext context,
+ ModuleChunk chunk,
+ DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
+ Collection<File> files,
+ OutputConsumer outputConsumer)
+ throws Exception {
+ ExitCode exitCode = ExitCode.NOTHING_DONE;
+
+ final boolean hasSourcesToCompile = !files.isEmpty();
+
+ if (!hasSourcesToCompile && !dirtyFilesHolder.hasRemovedFiles()) {
+ return exitCode;
+ }
+
+ final ProjectDescriptor pd = context.getProjectDescriptor();
+
+ JavaBuilderUtil.ensureModuleHasJdk(chunk.representativeTarget().getModule(), context, BUILDER_NAME);
+ final Collection<File> classpath = ProjectPaths.getCompilationClasspath(chunk, false/*context.isProjectRebuild()*/);
+ final Collection<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false/*context.isProjectRebuild()*/);
+
+ // begin compilation round
+ final DiagnosticSink diagnosticSink = new DiagnosticSink(context);
+ final Mappings delta = pd.dataManager.getMappings().createDelta();
+ final Callbacks.Backend mappingsCallback = delta.getCallback();
+ final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getName());
+ try {
+ if (hasSourcesToCompile) {
+ final AtomicReference<String> ref = COMPILER_VERSION_INFO.get(context);
+ final String versionInfo = ref.getAndSet(null); // display compiler version info only once per compile session
+ if (versionInfo != null) {
+ LOG.info(versionInfo);
+ context.processMessage(new CompilerMessage("", BuildMessage.Kind.INFO, versionInfo));
+ }
+ exitCode = ExitCode.OK;
+
+ final Set<File> srcPath = new HashSet<File>();
+ final BuildRootIndex index = pd.getBuildRootIndex();
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ for (JavaSourceRootDescriptor rd : index.getTempTargetRoots(target, context)) {
+ srcPath.add(rd.root);
+ }
+ }
+
+ final String chunkName = chunk.getName();
+ context.processMessage(new ProgressMessage("Parsing java... [" + chunkName + "]"));
+
+ final int filesCount = files.size();
+ boolean compiledOk = true;
+ if (filesCount > 0) {
+ LOG.info("Compiling " + filesCount + " java files; module: " + chunkName + (chunk.containsTests() ? " (tests)" : ""));
+ if (LOG.isDebugEnabled()) {
+ for (File file : files) {
+ LOG.debug("Compiling " + file.getPath());
+ }
+ LOG.debug(" classpath for " + chunkName + ":");
+ for (File file : classpath) {
+ LOG.debug(" " + file.getAbsolutePath());
+ }
+ LOG.debug(" platform classpath for " + chunkName + ":");
+ for (File file : platformCp) {
+ LOG.debug(" " + file.getAbsolutePath());
+ }
+ }
+ compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink);
+ }
+
+ context.checkCanceled();
+
+ if (!compiledOk && diagnosticSink.getErrorCount() == 0) {
+ diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Compilation failed: internal java compiler error"));
+ }
+ if (!Utils.PROCEED_ON_ERROR_KEY.get(context, Boolean.FALSE) && diagnosticSink.getErrorCount() > 0) {
+ if (!compiledOk) {
+ diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Errors occurred while compiling module '" + chunkName + "'"));
+ }
+ throw new ProjectBuildException(
+ "Compilation failed: errors: " + diagnosticSink.getErrorCount() + "; warnings: " + diagnosticSink.getWarningCount()
+ );
+ }
+ }
+ }
+ finally {
+ if (JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, files, outputSink.getSuccessfullyCompiled())) {
+ exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED;
+ }
+ }
+
+ return exitCode;
+ }
+
+ private boolean compileJava(
+ final CompileContext context,
+ ModuleChunk chunk,
+ Collection<File> files,
+ Collection<File> classpath,
+ Collection<File> platformCp,
+ Collection<File> sourcePath,
+ DiagnosticOutputConsumer diagnosticSink,
+ final OutputFileConsumer outputSink) throws Exception {
+
+ final TasksCounter counter = new TasksCounter();
+ COUNTER_KEY.set(context, counter);
+
+ final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance();
+ final JpsJavaCompilerConfiguration compilerConfig = javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject());
+ assert compilerConfig != null;
+
+ final Set<JpsModule> modules = chunk.getModules();
+ ProcessorConfigProfile profile = null;
+ if (modules.size() == 1) {
+ final JpsModule module = modules.iterator().next();
+ profile = compilerConfig.getAnnotationProcessingProfile(module);
+ }
+ else {
+ // perform cycle-related validations
+ Pair<String, LanguageLevel> pair = null;
+ for (JpsModule module : modules) {
+ final LanguageLevel moduleLevel = javaExt.getLanguageLevel(module);
+ if (pair == null) {
+ pair = Pair.create(module.getName(), moduleLevel); // first value
+ }
+ else {
+ if (!Comparing.equal(pair.getSecond(), moduleLevel)) {
+ final String message = "Modules " + pair.getFirst()+ " and " +module.getName() + " must have the same language level because of cyclic dependencies between them";
+ diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
+ return true;
+ }
+ }
+ }
+
+ // check that all chunk modules are excluded from annotation processing
+ for (JpsModule module : modules) {
+ final ProcessorConfigProfile prof = compilerConfig.getAnnotationProcessingProfile(module);
+ if (prof.isEnabled()) {
+ final String message = "Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [" + chunk.getName() + "] are excluded from annotation processing";
+ diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
+ return true;
+ }
+ }
+ }
+
+ final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk);
+ final List<String> options = getCompilationOptions(context, chunk, profile);
+ final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\"");
+ }
+ try {
+ final boolean rc;
+ if (USE_EMBEDDED_JAVAC) {
+ final boolean useEclipse = useEclipseCompiler(context);
+ rc = JavacMain.compile(
+ options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus(), useEclipse
+ );
+ }
+ else {
+ final JavacServerClient client = ensureJavacServerLaunched(context);
+ final RequestFuture<JavacServerResponseHandler> future = client.sendCompileRequest(
+ options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer
+ );
+ while (!future.waitFor(100L, TimeUnit.MILLISECONDS)) {
+ if (context.getCancelStatus().isCanceled()) {
+ future.cancel(false);
+ }
+ }
+ rc = future.getMessageHandler().isTerminatedSuccessfully();
+ }
+ return rc;
+ }
+ finally {
+ counter.await();
+ }
+ }
+
+ private static boolean useEclipseCompiler(CompileContext context) {
+ if (!USE_EMBEDDED_JAVAC) {
+ return false;
+ }
+ JpsProject project = context.getProjectDescriptor().getProject();
+ final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
+ final String compilerId = configuration != null? configuration.getJavaCompilerId() : null;
+ return JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
+ }
+
+ private void submitAsyncTask(CompileContext context, final Runnable taskRunnable) {
+ final TasksCounter counter = COUNTER_KEY.get(context);
+
+ assert counter != null;
+
+ counter.incTaskCount();
+ myTaskRunner.execute(new Runnable() {
+ public void run() {
+ try {
+ taskRunnable.run();
+ }
+ finally {
+ counter.decTaskCounter();
+ }
+ }
+ });
+ }
+
+ private static synchronized JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception {
+ final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context);
+ if (descriptor != null) {
+ return descriptor.client;
+ }
+ // start server here
+ final int port = findFreePort();
+ final int heapSize = getJavacServerHeapSize(context);
+
+ // defaulting to the same jdk that used to run the build process
+ String javaHome = SystemProperties.getJavaHome();
+ int javaVersion = convertToNumber(SystemProperties.getJavaVersion());
+
+ for (JpsSdk<?> sdk : context.getProjectDescriptor().getProjectJavaSdks()) {
+ final String version = sdk.getVersionString();
+ final int ver = convertToNumber(version);
+ if (ver > javaVersion) {
+ javaVersion = ver;
+ javaHome = sdk.getHomePath();
+ }
+ }
+
+ final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer(
+ javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context)
+ );
+ final JavacServerClient client = new JavacServerClient();
+ try {
+ client.connect("127.0.0.1", port);
+ }
+ catch (Throwable ex) {
+ processHandler.destroyProcess();
+ throw new Exception("Failed to connect to external javac process: ", ex);
+ }
+ ExternalJavacDescriptor.KEY.set(context, new ExternalJavacDescriptor(processHandler, client));
+ return client;
+ }
+
+ private static int convertToNumber(String ver) {
+ if (ver == null) {
+ return 0;
+ }
+ final int quoteBegin = ver.indexOf("\"");
+ if (quoteBegin >= 0) {
+ final int quoteEnd = ver.indexOf("\"", quoteBegin + 1);
+ if (quoteEnd > quoteBegin) {
+ ver = ver.substring(quoteBegin + 1, quoteEnd);
+ }
+ }
+ if (ver.isEmpty()) {
+ return 0;
+ }
+
+ final String prefix = "1.";
+ final int parseBegin = ver.startsWith(prefix)? prefix.length() : 0;
+
+ final int parseEnd = ver.indexOf(".", parseBegin);
+ if (parseEnd > 0) {
+ ver = ver.substring(parseBegin, parseEnd);
+ }
+ else {
+ ver = ver.substring(parseBegin);
+ }
+
+ try {
+ return Integer.parseInt(ver);
+ }
+ catch (NumberFormatException ignored) {
+ }
+ return 0;
+ }
+
+ private static int findFreePort() {
+ try {
+ final ServerSocket serverSocket = new ServerSocket(0);
+ try {
+ return serverSocket.getLocalPort();
+ }
+ finally {
+ //workaround for linux : calling close() immediately after opening socket
+ //may result that socket is not closed
+ synchronized (serverSocket) {
+ try {
+ serverSocket.wait(1);
+ }
+ catch (Throwable ignored) {
+ }
+ }
+ serverSocket.close();
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace(System.err);
+ return JavacServer.DEFAULT_SERVER_PORT;
+ }
+ }
+
+ private static int getJavacServerHeapSize(CompileContext context) {
+ final JpsProject project = context.getProjectDescriptor().getProject();
+ final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ final JpsJavaCompilerOptions options = config.getCurrentCompilerOptions();
+ return options.MAXIMUM_HEAP_SIZE;
+ }
+
+ private static final Key<List<String>> JAVAC_OPTIONS = Key.create("_javac_options_");
+ private static final Key<List<String>> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_");
+
+ private static List<String> getCompilationVMOptions(CompileContext context) {
+ List<String> cached = JAVAC_VM_OPTIONS.get(context);
+ if (cached == null) {
+ loadCommonJavacOptions(context);
+ cached = JAVAC_VM_OPTIONS.get(context);
+ }
+ return cached;
+ }
+
+ private static List<String> getCompilationOptions(CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile) {
+ List<String> cached = JAVAC_OPTIONS.get(context);
+ if (cached == null) {
+ loadCommonJavacOptions(context);
+ cached = JAVAC_OPTIONS.get(context);
+ assert cached != null : context;
+ }
+
+ List<String> options = new ArrayList<String>(cached);
+ addCompilationOptions(options, context, chunk, profile);
+ return options;
+ }
+
+ public static void addCompilationOptions(List<String> options, CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile) {
+ if (!isEncodingSet(options)) {
+ final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration();
+ final String encoding = config.getPreferredModuleChunkEncoding(chunk);
+ if (config.getAllModuleChunkEncodings(chunk).size() > 1) {
+ final StringBuilder msgBuilder = new StringBuilder();
+ msgBuilder.append("Multiple encodings set for module chunk ").append(chunk.getName());
+ if (encoding != null) {
+ msgBuilder.append("\n\"").append(encoding).append("\" will be used by compiler");
+ }
+ context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, msgBuilder.toString()));
+ }
+ if (!StringUtil.isEmpty(encoding)) {
+ options.add("-encoding");
+ options.add(encoding);
+ }
+ }
+
+ final String langLevel = getLanguageLevel(chunk.getModules().iterator().next());
+ if (!StringUtil.isEmpty(langLevel)) {
+ options.add("-source");
+ options.add(langLevel);
+ }
+
+ JpsJavaCompilerConfiguration compilerConfiguration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(
+ context.getProjectDescriptor().getProject());
+ String bytecodeTarget = null;
+ int chunkSdkVersion = -1;
+ for (JpsModule module : chunk.getModules()) {
+ final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE);
+ if (sdk != null) {
+ final int moduleSdkVersion = convertToNumber(sdk.getVersionString());
+ if (moduleSdkVersion != 0 /*could determine the version*/&& (chunkSdkVersion < 0 || chunkSdkVersion > moduleSdkVersion)) {
+ chunkSdkVersion = moduleSdkVersion;
+ }
+ }
+
+ final String moduleTarget = compilerConfiguration.getByteCodeTargetLevel(module.getName());
+ if (moduleTarget == null) {
+ continue;
+ }
+ if (bytecodeTarget == null) {
+ bytecodeTarget = moduleTarget;
+ }
+ else {
+ if (moduleTarget.compareTo(bytecodeTarget) < 0) {
+ bytecodeTarget = moduleTarget; // use the lower possible target among modules that form the chunk
+ }
+ }
+ }
+ if (bytecodeTarget != null) {
+ options.add("-target");
+ options.add(bytecodeTarget);
+ }
+ else {
+ if (chunkSdkVersion > 0 && getCompilerSdkVersion(context) > chunkSdkVersion) {
+ // force lower bytecode target level to match the version of sdk assigned to this chunk
+ options.add("-target");
+ options.add("1." + chunkSdkVersion);
+ }
+ }
+
+ if (profile != null && profile.isEnabled()) {
+ // configuring annotation processing
+ if (!profile.isObtainProcessorsFromClasspath()) {
+ final String processorsPath = profile.getProcessorPath();
+ options.add("-processorpath");
+ options.add(processorsPath == null? "" : FileUtil.toSystemDependentName(processorsPath.trim()));
+ }
+
+ final Set<String> processors = profile.getProcessors();
+ if (!processors.isEmpty()) {
+ options.add("-processor");
+ options.add(StringUtil.join(processors, ","));
+ }
+
+ for (Map.Entry<String, String> optionEntry : profile.getProcessorOptions().entrySet()) {
+ options.add("-A" + optionEntry.getKey() + "=" + optionEntry.getValue());
+ }
+
+ final File srcOutput = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir(
+ chunk.getModules().iterator().next(), chunk.containsTests(), profile
+ );
+ if (srcOutput != null) {
+ srcOutput.mkdirs();
+ options.add("-s");
+ options.add(srcOutput.getPath());
+ }
+ }
+ else {
+ options.add("-proc:none");
+ }
+ }
+
+ private static String getLanguageLevel(JpsModule module) {
+ LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(module);
+ if (level == null) return null;
+ switch (level) {
+ case JDK_1_3: return "1.3";
+ case JDK_1_4: return "1.4";
+ case JDK_1_5: return "1.5";
+ case JDK_1_6: return "1.6";
+ case JDK_1_7: return "1.7";
+ case JDK_1_8: return "8";
+ default: return null;
+ }
+ }
+
+ private static boolean isEncodingSet(List<String> options) {
+ for (String option : options) {
+ if ("-encoding".equals(option)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private static int getCompilerSdkVersion(CompileContext context) {
+ final Integer cached = JAVA_COMPILER_VERSION_KEY.get(context);
+ if (cached != null) {
+ return cached;
+ }
+ int javaVersion = convertToNumber(SystemProperties.getJavaVersion());
+ if (!USE_EMBEDDED_JAVAC) {
+ // in case of external javac, run compiler from the newest jdk that is used in the project
+ for (JpsSdk<?> sdk : context.getProjectDescriptor().getProjectJavaSdks()) {
+ final String version = sdk.getVersionString();
+ final int ver = convertToNumber(version);
+ if (ver > javaVersion) {
+ javaVersion = ver;
+ }
+ }
+ }
+ JAVA_COMPILER_VERSION_KEY.set(context, javaVersion);
+ return javaVersion;
+ }
+
+ private static void loadCommonJavacOptions(CompileContext context) {
+ final List<String> options = new ArrayList<String>();
+ final List<String> vmOptions = new ArrayList<String>();
+
+ final JpsProject project = context.getProjectDescriptor().getProject();
+ final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ final JpsJavaCompilerOptions compilerOptions = compilerConfig.getCurrentCompilerOptions();
+ if (compilerOptions.DEBUGGING_INFO) {
+ options.add("-g");
+ }
+ if (compilerOptions.DEPRECATION) {
+ options.add("-deprecation");
+ }
+ if (compilerOptions.GENERATE_NO_WARNINGS) {
+ options.add("-nowarn");
+ }
+ if (compilerOptions instanceof EclipseCompilerOptions) {
+ final EclipseCompilerOptions eclipseOptions = (EclipseCompilerOptions)compilerOptions;
+ if (eclipseOptions.PROCEED_ON_ERROR) {
+ options.add("-proceedOnError");
+ }
+ }
+ final String customArgs = compilerOptions.ADDITIONAL_OPTIONS_STRING;
+ if (customArgs != null) {
+ final StringTokenizer customOptsTokenizer = new StringTokenizer(customArgs, " \t\r\n");
+ boolean skip = false;
+ while (customOptsTokenizer.hasMoreTokens()) {
+ final String userOption = customOptsTokenizer.nextToken();
+ if (FILTERED_OPTIONS.contains(userOption)) {
+ skip = true;
+ continue;
+ }
+ if (!skip) {
+ if (!FILTERED_SINGLE_OPTIONS.contains(userOption)) {
+ if (userOption.startsWith("-J-")) {
+ vmOptions.add(userOption.substring("-J".length()));
+ }
+ else {
+ options.add(userOption);
+ }
+ }
+ }
+ }
+ }
+
+ if (useEclipseCompiler(context)) {
+ for (String option : options) {
+ if (option.startsWith("-proceedOnError")) {
+ Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE);
+ break;
+ }
+ }
+ }
+
+ JAVAC_OPTIONS.set(context, options);
+ JAVAC_VM_OPTIONS.set(context, vmOptions);
+ }
+
+ @Override
+ public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
+ JavaBuilderUtil.cleanupChunkResources(context);
+ }
+
+ private static Map<File, Set<File>> buildOutputDirectoriesMap(CompileContext context, ModuleChunk chunk) {
+ final Map<File, Set<File>> map = new THashMap<File, Set<File>>(FileUtil.FILE_HASHING_STRATEGY);
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ final File outputDir = target.getOutputDir();
+ if (outputDir == null) {
+ continue;
+ }
+ final Set<File> roots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ for (JavaSourceRootDescriptor descriptor : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) {
+ roots.add(descriptor.root);
+ }
+ map.put(outputDir, roots);
+ }
+ return map;
+ }
+
+ private class DiagnosticSink implements DiagnosticOutputConsumer {
+ private final CompileContext myContext;
+ private volatile int myErrorCount = 0;
+ private volatile int myWarningCount = 0;
+
+ public DiagnosticSink(CompileContext context) {
+ myContext = context;
+ }
+
+ public void registerImports(final String className, final Collection<String> imports, final Collection<String> staticImports) {
+ //submitAsyncTask(myContext, new Runnable() {
+ // public void run() {
+ // final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(myContext);
+ // if (callback != null) {
+ // callback.registerImports(className, imports, staticImports);
+ // }
+ // }
+ //});
+ }
+
+ public void outputLineAvailable(String line) {
+ if (!StringUtil.isEmpty(line)) {
+ if (line.contains("java.lang.OutOfMemoryError")) {
+ myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "OutOfMemoryError: insufficient memory"));
+ myErrorCount++;
+ }
+ else {
+ final BuildMessage.Kind kind = getKindByMessageText(line);
+ if (kind == BuildMessage.Kind.ERROR) {
+ myErrorCount++;
+ }
+ else if (kind == BuildMessage.Kind.WARNING) {
+ myWarningCount++;
+ }
+ myContext.processMessage(new CompilerMessage(BUILDER_NAME, kind, line));
+ }
+ }
+ }
+
+ private BuildMessage.Kind getKindByMessageText(String line) {
+ final String lowercasedLine = line.toLowerCase(Locale.US);
+ if (lowercasedLine.contains("error") || lowercasedLine.contains("requires target release")) {
+ return BuildMessage.Kind.ERROR;
+ }
+ return BuildMessage.Kind.INFO;
+ }
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ final CompilerMessage.Kind kind;
+ switch (diagnostic.getKind()) {
+ case ERROR:
+ kind = BuildMessage.Kind.ERROR;
+ myErrorCount++;
+ break;
+ case MANDATORY_WARNING:
+ case WARNING:
+ case NOTE:
+ kind = BuildMessage.Kind.WARNING;
+ myWarningCount++;
+ break;
+ default:
+ kind = BuildMessage.Kind.INFO;
+ }
+ final JavaFileObject source = diagnostic.getSource();
+ File sourceFile = null;
+ try {
+ sourceFile = source != null ? Utils.convertToFile(source.toUri()) : null;
+ }
+ catch (Exception e) {
+ LOG.info(e);
+ }
+ final String srcPath = sourceFile != null ? FileUtil.toSystemIndependentName(sourceFile.getPath()) : null;
+ String message = diagnostic.getMessage(Locale.US);
+ if (Utils.IS_TEST_MODE) {
+ LOG.info(message);
+ }
+ myContext.processMessage(
+ new CompilerMessage(BUILDER_NAME, kind, message, srcPath, diagnostic.getStartPosition(),
+ diagnostic.getEndPosition(), diagnostic.getPosition(), diagnostic.getLineNumber(),
+ diagnostic.getColumnNumber()));
+ }
+
+ public int getErrorCount() {
+ return myErrorCount;
+ }
+
+ public int getWarningCount() {
+ return myWarningCount;
+ }
+ }
+
+ private class ClassProcessingConsumer implements OutputFileConsumer {
+ private final CompileContext myContext;
+ private final OutputFileConsumer myDelegateOutputFileSink;
+
+ public ClassProcessingConsumer(CompileContext context, OutputFileConsumer sink) {
+ myContext = context;
+ myDelegateOutputFileSink = sink != null ? sink : new OutputFileConsumer() {
+ public void save(@NotNull OutputFileObject fileObject) {
+ throw new RuntimeException("Output sink for compiler was not specified");
+ }
+ };
+ }
+
+ public void save(@NotNull final OutputFileObject fileObject) {
+ submitAsyncTask(myContext, new Runnable() {
+ public void run() {
+ try {
+ for (ClassPostProcessor processor : ourClassProcessors) {
+ processor.process(myContext, fileObject);
+ }
+ }
+ finally {
+ myDelegateOutputFileSink.save(fileObject);
+ }
+ }
+ });
+ }
+ }
+
+
+ private static final Key<TasksCounter> COUNTER_KEY = Key.create("_async_task_counter_");
+
+ private static final class TasksCounter {
+ private int myCounter = 0;
+
+ public synchronized void incTaskCount() {
+ myCounter++;
+ }
+
+ public synchronized void decTaskCounter() {
+ myCounter = Math.max(0, myCounter - 1);
+ if (myCounter == 0) {
+ notifyAll();
+ }
+ }
+
+ public synchronized void await() {
+ while (myCounter > 0) {
+ try {
+ wait();
+ }
+ catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
new file mode 100644
index 000000000000..9508b86b842f
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.java;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.javac.OutputFileConsumer;
+import org.jetbrains.jps.javac.OutputFileObject;
+
+import javax.tools.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 2/16/12
+*/
+class OutputFilesSink implements OutputFileConsumer {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.OutputFilesSink");
+
+ private final CompileContext myContext;
+ private final ModuleLevelBuilder.OutputConsumer myOutputConsumer;
+ private final Callbacks.Backend myMappingsCallback;
+ private final String myChunkName;
+ private final Set<File> mySuccessfullyCompiled = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+ public OutputFilesSink(CompileContext context,
+ ModuleLevelBuilder.OutputConsumer outputConsumer,
+ Callbacks.Backend callback,
+ String chunkName) {
+ myContext = context;
+ myOutputConsumer = outputConsumer;
+ myMappingsCallback = callback;
+ myChunkName = "[" +chunkName + "]";
+ }
+
+ public void save(final @NotNull OutputFileObject fileObject) {
+ final BinaryContent content = fileObject.getContent();
+ final File srcFile = fileObject.getSourceFile();
+ boolean isTemp = false;
+ final JavaFileObject.Kind outKind = fileObject.getKind();
+
+ if (srcFile != null && content != null) {
+ final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
+ final JavaSourceRootDescriptor rootDescriptor = myContext.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(myContext, srcFile);
+ if (rootDescriptor != null) {
+ isTemp = rootDescriptor.isTemp;
+ if (!isTemp) {
+ // first, handle [src->output] mapping and register paths for files_generated event
+ try {
+ if (outKind == JavaFileObject.Kind.CLASS) {
+ myOutputConsumer.registerCompiledClass(rootDescriptor.target, new CompiledClass(fileObject.getFile(), srcFile, fileObject.getClassName(), content)); // todo: avoid array copying?
+ }
+ else {
+ myOutputConsumer.registerOutputFile(rootDescriptor.target, fileObject.getFile(), Collections.<String>singleton(sourcePath));
+ }
+ }
+ catch (IOException e) {
+ myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, e));
+ }
+ }
+ }
+
+ if (!isTemp && outKind == JavaFileObject.Kind.CLASS && !Utils.errorsDetected(myContext)) {
+ // register in mappings any non-temp class file
+ final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
+ myMappingsCallback.associate(FileUtil.toSystemIndependentName(fileObject.getFile().getPath()), sourcePath, reader);
+ }
+ }
+
+ try {
+ writeToDisk(fileObject, isTemp);
+ }
+ catch (IOException e) {
+ myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage()));
+ }
+ }
+
+ public Set<File> getSuccessfullyCompiled() {
+ return Collections.unmodifiableSet(mySuccessfullyCompiled);
+ }
+
+ private void writeToDisk(@NotNull OutputFileObject fileObject, boolean isTemp) throws IOException {
+ myContext.processMessage(new ProgressMessage("Writing classes... " + myChunkName));
+
+ final File file = fileObject.getFile();
+ final BinaryContent content = fileObject.getContent();
+ if (content == null) {
+ throw new IOException("Missing content for file " + file);
+ }
+
+ content.saveToFile(file);
+
+ final File source = fileObject.getSourceFile();
+ if (!isTemp && source != null) {
+ mySuccessfullyCompiled.add(source);
+ //final String className = fileObject.getClassName();
+ //if (className != null) {
+ // myContext.processMessage(new ProgressMessage("Compiled " + className));
+ //}
+ }
+ }
+
+ public void markError(@NotNull final File sourceFile) {
+ mySuccessfullyCompiled.remove(sourceFile);
+ }
+ public void markError(@NotNull final Set<File> problematic) {
+ mySuccessfullyCompiled.removeAll(problematic);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildMessage.java
new file mode 100644
index 000000000000..3fad1fbc699d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildMessage.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public abstract class BuildMessage {
+ public static enum Kind {
+ ERROR, WARNING, INFO, PROGRESS
+ }
+
+ private final String myMessageText;
+ private final Kind myKind;
+
+ protected BuildMessage(String messageText, Kind kind) {
+ myMessageText = messageText;
+ myKind = kind;
+ }
+
+ public Kind getKind() {
+ return myKind;
+ }
+
+ public String getMessageText() {
+ return myMessageText;
+ }
+
+ public String toString() {
+ return getMessageText();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
new file mode 100644
index 000000000000..90580fccd3ec
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public class CompilerMessage extends BuildMessage {
+
+ private final String myCompilerName;
+ private final long myProblemBeginOffset;
+ private final long myProblemEndOffset;
+ private final long myProblemLocationOffset;
+ private final String mySourcePath;
+ private final long myLine;
+ private final long myColumn;
+
+ public CompilerMessage(String compilerName, Throwable internalError) {
+ this(compilerName, Kind.ERROR, getTextFromThrowable(internalError), null, -1L, -1L, -1L, -1L, -1L);
+ }
+
+ public CompilerMessage(String compilerName, Kind kind, String messageText) {
+ this(compilerName, kind, messageText, null, -1L, -1L, -1L, -1L, -1L);
+ }
+
+ public CompilerMessage(String compilerName, Kind kind, String messageText, String sourcePath) {
+ this(compilerName, kind, messageText, sourcePath, -1L, -1L, -1L, -1L, -1L);
+ }
+
+ public CompilerMessage(String compilerName, Kind kind, String messageText,
+ @Nullable String sourcePath,
+ long problemBeginOffset,
+ long problemEndOffset,
+ long problemLocationOffset,
+ long locationLine,
+ long locationColumn) {
+ super(messageText, kind);
+ myCompilerName = compilerName;
+ myProblemBeginOffset = problemBeginOffset;
+ myProblemEndOffset = problemEndOffset;
+ myProblemLocationOffset = problemLocationOffset;
+ mySourcePath = sourcePath != null && !sourcePath.isEmpty()? sourcePath.replace(File.separatorChar, '/') : null;
+ myLine = locationLine;
+ myColumn = locationColumn;
+ }
+
+ public String getCompilerName() {
+ return myCompilerName;
+ }
+
+ @Nullable
+ public String getSourcePath() {
+ return mySourcePath;
+ }
+
+ public long getLine() {
+ return myLine;
+ }
+
+ public long getColumn() {
+ return myColumn;
+ }
+
+ public long getProblemBeginOffset() {
+ return myProblemBeginOffset;
+ }
+
+ public long getProblemEndOffset() {
+ return myProblemEndOffset;
+ }
+
+ public long getProblemLocationOffset() {
+ return myProblemLocationOffset;
+ }
+
+ public String toString() {
+ return getCompilerName() + ":" + getKind().name() + ":" + super.toString();
+ }
+
+ private static String getTextFromThrowable(Throwable internalError) {
+ StringBuilder text = new StringBuilder();
+ text.append("Error: ");
+ final String msg = internalError.getMessage();
+ if (msg != null) {
+ text.append(msg);
+ }
+ else {
+ text.append(internalError.getClass().getName());
+ }
+ text.append("\n");
+
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ internalError.printStackTrace(new PrintStream(out));
+ text.append(out.toString());
+
+ return text.toString();
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CustomBuilderMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CustomBuilderMessage.java
new file mode 100644
index 000000000000..147ef0f365f7
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CustomBuilderMessage.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+/**
+ * @author nik
+ */
+public class CustomBuilderMessage extends BuildMessage {
+ private final String myBuilderId;
+ private final String myMessageType;
+ private final String myMessageText;
+
+ public CustomBuilderMessage(String builderId, String messageType, String messageText) {
+ super("", Kind.INFO);
+ myBuilderId = builderId;
+ myMessageType = messageType;
+ myMessageText = messageText;
+ }
+
+ public String getBuilderId() {
+ return myBuilderId;
+ }
+
+ public String getMessageType() {
+ return myMessageType;
+ }
+
+ public String getMessageText() {
+ return myMessageText;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/DoneSomethingNotification.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/DoneSomethingNotification.java
new file mode 100644
index 000000000000..e2e8c97ca015
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/DoneSomethingNotification.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public class DoneSomethingNotification extends BuildMessage {
+ public static DoneSomethingNotification INSTANCE = new DoneSomethingNotification();
+
+ private DoneSomethingNotification() {
+ super("", Kind.INFO);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileDeletedEvent.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileDeletedEvent.java
new file mode 100644
index 000000000000..fbae82e05ea5
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileDeletedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public class FileDeletedEvent extends BuildMessage {
+ private Collection<String> myFilePaths;
+
+ public FileDeletedEvent(Collection<String> filePaths) {
+ super("", Kind.INFO);
+ myFilePaths = filePaths;
+ }
+
+ public Collection<String> getFilePaths() {
+ return myFilePaths;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java
new file mode 100644
index 000000000000..99084dfb9011
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public class FileGeneratedEvent extends BuildMessage {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.messages.FileGeneratedEvent");
+
+ private final Collection<Pair<String, String>> myPaths = new ArrayList<Pair<String, String>>();
+
+ public FileGeneratedEvent() {
+ super("", Kind.INFO);
+ }
+
+ public void add(String root, String relativePath) {
+ if (root != null && relativePath != null) {
+ myPaths.add(new Pair<String, String>(FileUtil.toSystemIndependentName(root), FileUtil.toSystemIndependentName(relativePath)));
+ }
+ else {
+ LOG.info("Invalid file generation event: root=" + root + "; relativePath=" + relativePath);
+ }
+ }
+
+ public Collection<Pair<String, String>> getPaths() {
+ return myPaths;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/ProgressMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/ProgressMessage.java
new file mode 100644
index 000000000000..1f5b974b3ba5
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/ProgressMessage.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.messages;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/29/11
+ */
+public class ProgressMessage extends BuildMessage {
+ private volatile float myDone;
+
+ public ProgressMessage(String messageText) {
+ this(messageText, -1.0f);
+ }
+
+ public ProgressMessage(String messageText, float done) {
+ super(messageText, Kind.PROGRESS);
+ myDone = done;
+ }
+
+ public float getDone() {
+ return myDone;
+ }
+
+ public void setDone(float done) {
+ myDone = done;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
new file mode 100644
index 000000000000..f07df2ec467c
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.resources;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/6/11
+ */
+public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, ResourcesTarget> {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.resourses.ResourcesBuilder");
+ public static final String BUILDER_NAME = "Resource Compiler";
+ private static final List<StandardResourceBuilderEnabler> ourEnablers = Collections.synchronizedList(new ArrayList<StandardResourceBuilderEnabler>());
+
+ public ResourcesBuilder() {
+ super(ResourcesTargetType.ALL_TYPES);
+ }
+
+ public static void registerEnabler(StandardResourceBuilderEnabler enabler) {
+ ourEnablers.add(enabler);
+ }
+
+ @Override
+ public void buildStarted(CompileContext context) {
+ // init patterns
+ ResourcePatterns patterns = ResourcePatterns.KEY.get(context);
+ if (patterns == null) {
+ ResourcePatterns.KEY.set(context, new ResourcePatterns(context.getProjectDescriptor().getProject()));
+ }
+ }
+
+ @Override
+ public void build(@NotNull ResourcesTarget target,
+ @NotNull DirtyFilesHolder<ResourceRootDescriptor, ResourcesTarget> holder,
+ @NotNull final BuildOutputConsumer outputConsumer,
+ @NotNull final CompileContext context) throws ProjectBuildException, IOException {
+
+ if (!isResourceProcessingEnabled(target.getModule())) {
+ return;
+ }
+
+ @Nullable
+ final Map<ResourcesTarget, Set<File>> cleanedSources;
+ if (context.isProjectRebuild()) {
+ cleanedSources = null;
+ }
+ else {
+ cleanedSources = BuildOperations.cleanOutputsCorrespondingToChangedFiles(context, holder);
+ }
+
+ final ResourcePatterns patterns = ResourcePatterns.KEY.get(context);
+ assert patterns != null;
+
+ try {
+ holder.processDirtyFiles(new FileProcessor<ResourceRootDescriptor, ResourcesTarget>() {
+ private final Map<ResourceRootDescriptor, Boolean> mySkippedRoots = new HashMap<ResourceRootDescriptor, Boolean>();
+ public boolean apply(ResourcesTarget target, final File file, final ResourceRootDescriptor sourceRoot) throws IOException {
+ Boolean isSkipped = mySkippedRoots.get(sourceRoot);
+ if (isSkipped == null) {
+ final File outputDir = target.getOutputDir();
+ isSkipped = Boolean.valueOf(outputDir == null || FileUtil.filesEqual(outputDir, sourceRoot.getRootFile()));
+ mySkippedRoots.put(sourceRoot, isSkipped);
+ }
+ if (isSkipped.booleanValue()) {
+ return true;
+ }
+ if (patterns.isResourceFile(file, sourceRoot.getRootFile())) {
+ try {
+ copyResource(context, sourceRoot, file, outputConsumer);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ context.processMessage(
+ new CompilerMessage(
+ "resources", BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(file.getPath())
+ )
+ );
+ return false;
+ }
+ finally {
+ if (cleanedSources != null) {
+ final Set<File> files = cleanedSources.get(target);
+ if (files != null) {
+ files.remove(file);
+ }
+ }
+ }
+ }
+ return !context.getCancelStatus().isCanceled();
+ }
+ });
+
+ context.checkCanceled();
+
+ if (cleanedSources != null) {
+ // cleanup mapping for the files that were copied before but not copied now
+ for (Map.Entry<ResourcesTarget, Set<File>> entry : cleanedSources.entrySet()) {
+ final Set<File> files = entry.getValue();
+ if (!files.isEmpty()) {
+ final SourceToOutputMapping mapping = context.getProjectDescriptor().dataManager.getSourceToOutputMap(entry.getKey());
+ for (File file : files) {
+ mapping.remove(file.getPath());
+ }
+ }
+ }
+ }
+
+ context.processMessage(new ProgressMessage(""));
+ }
+ catch (Exception e) {
+ throw new ProjectBuildException(e.getMessage(), e);
+ }
+ }
+
+ private static boolean isResourceProcessingEnabled(JpsModule module) {
+ synchronized (ourEnablers) {
+ for (StandardResourceBuilderEnabler enabler : ourEnablers) {
+ if (!enabler.isResourceProcessingEnabled(module)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static void copyResource(CompileContext context, ResourceRootDescriptor rd, File file, BuildOutputConsumer outputConsumer) throws IOException {
+ final File outputRoot = rd.getTarget().getOutputDir();
+ if (outputRoot == null) {
+ return;
+ }
+ final String sourceRootPath = FileUtil.toSystemIndependentName(rd.getRootFile().getAbsolutePath());
+ final String relativePath = FileUtil.getRelativePath(sourceRootPath, FileUtil.toSystemIndependentName(file.getPath()), '/');
+ final String prefix = rd.getPackagePrefix();
+
+ final StringBuilder targetPath = new StringBuilder();
+ targetPath.append(FileUtil.toSystemIndependentName(outputRoot.getPath()));
+ if (prefix.length() > 0) {
+ targetPath.append('/').append(prefix.replace('.', '/'));
+ }
+ targetPath.append('/').append(relativePath);
+
+ context.processMessage(new ProgressMessage("Copying resources... [" + rd.getTarget().getModule().getName() + "]"));
+
+ final String outputPath = targetPath.toString();
+ final File targetFile = new File(outputPath);
+ FileUtil.copyContent(file, targetFile);
+ try {
+ outputConsumer.registerOutputFile(targetFile, Collections.singletonList(file.getPath()));
+ }
+ catch (Exception e) {
+ context.processMessage(new CompilerMessage(BUILDER_NAME, e));
+ }
+ }
+
+ @NotNull
+ public String getPresentableName() {
+ return "Resource Compiler";
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/StandardResourceBuilderEnabler.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/StandardResourceBuilderEnabler.java
new file mode 100644
index 000000000000..68d5d015ca2b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/StandardResourceBuilderEnabler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.resources;
+
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/20/12
+ */
+public interface StandardResourceBuilderEnabler {
+ boolean isResourceProcessingEnabled(JpsModule module);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/AbstractStateStorage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/AbstractStateStorage.java
new file mode 100644
index 000000000000..71f097fdd9cf
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/AbstractStateStorage.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+public abstract class AbstractStateStorage<Key, T> implements StorageOwner {
+ private PersistentHashMap<Key, T> myMap;
+ private final File myBaseFile;
+ private final KeyDescriptor<Key> myKeyDescriptor;
+ private final DataExternalizer<T> myStateExternalizer;
+ protected final Object myDataLock = new Object();
+
+ public AbstractStateStorage(@NonNls File storePath, KeyDescriptor<Key> keyDescriptor, DataExternalizer<T> stateExternalizer) throws IOException {
+ myBaseFile = storePath;
+ myKeyDescriptor = keyDescriptor;
+ myStateExternalizer = stateExternalizer;
+ myMap = createMap(storePath);
+ }
+
+ public void force() {
+ synchronized (myDataLock) {
+ myMap.force();
+ }
+ }
+
+ public void dropMemoryCache() {
+ synchronized (myDataLock) {
+ if (myMap.isDirty()) {
+ myMap.dropMemoryCaches();
+ }
+ }
+ }
+
+ public void close() throws IOException {
+ synchronized (myDataLock) {
+ myMap.close();
+ }
+ }
+
+ @Override
+ public void clean() throws IOException {
+ wipe();
+ }
+
+ public boolean wipe() {
+ synchronized (myDataLock) {
+ try {
+ myMap.close();
+ }
+ catch (IOException ignored) {
+ }
+ PersistentHashMap.deleteFilesStartingWith(myBaseFile);
+ try {
+ myMap = createMap(myBaseFile);
+ }
+ catch (IOException ignored) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public void update(Key key, @Nullable T state) throws IOException {
+ if (state != null) {
+ synchronized (myDataLock) {
+ myMap.put(key, state);
+ }
+ }
+ else {
+ remove(key);
+ }
+ }
+
+ public void appendData(final Key key, final T data) throws IOException {
+ synchronized (myDataLock) {
+ myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
+ public void append(DataOutput out) throws IOException {
+ myStateExternalizer.save(out, data);
+ }
+ });
+ }
+ }
+
+ public void remove(Key key) throws IOException {
+ synchronized (myDataLock) {
+ myMap.remove(key);
+ }
+ }
+
+ @Nullable
+ public T getState(Key key) throws IOException {
+ synchronized (myDataLock) {
+ return myMap.get(key);
+ }
+ }
+
+ public Collection<Key> getKeys() throws IOException {
+ synchronized (myDataLock) {
+ return myMap.getAllKeysWithExistingMapping();
+ }
+ }
+
+ public Iterator<Key> getKeysIterator() throws IOException {
+ synchronized (myDataLock) {
+ return myMap.getAllKeysWithExistingMapping().iterator();
+ }
+ }
+
+
+ private PersistentHashMap<Key, T> createMap(final File file) throws IOException {
+ FileUtil.createIfDoesntExist(file);
+ return new PersistentHashMap<Key,T>(file, myKeyDescriptor, myStateExternalizer);
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ if (memoryCachesOnly) {
+ dropMemoryCache();
+ }
+ else {
+ force();
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
new file mode 100644
index 000000000000..522c66ad9360
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.impl.BuildTargetChunk;
+import org.jetbrains.jps.builders.impl.storage.BuildTargetStorages;
+import org.jetbrains.jps.builders.java.dependencyView.Mappings;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+import org.jetbrains.jps.builders.storage.StorageProvider;
+
+import java.io.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/7/11
+ */
+public class BuildDataManager implements StorageOwner {
+ private static final int VERSION = 19;
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
+ private static final String SRC_TO_FORM_STORAGE = "src-form";
+ private static final String MAPPINGS_STORAGE = "mappings";
+
+ private final Object mySourceToOutputLock = new Object();
+ private final Map<BuildTarget<?>, SourceToOutputMappingImpl> mySourceToOutputs = new HashMap<BuildTarget<?>, SourceToOutputMappingImpl>();
+ private final Object myTargetStoragesLock = new Object();
+ private final Map<BuildTarget<?>, BuildTargetStorages> myTargetStorages = new HashMap<BuildTarget<?>, BuildTargetStorages>();
+ private StorageOwner myTargetStoragesOwner = new CompositeStorageOwner() {
+ @Override
+ protected Iterable<? extends StorageOwner> getChildStorages() {
+ return myTargetStorages.values();
+ }
+ };
+
+ private final OneToManyPathsMapping mySrcToFormMap;
+ private final Mappings myMappings;
+ private final BuildDataPaths myDataPaths;
+ private final BuildTargetsState myTargetsState;
+ private final File myVersionFile;
+
+ public BuildDataManager(final BuildDataPaths dataPaths, BuildTargetsState targetsState, final boolean useMemoryTempCaches) throws IOException {
+ myDataPaths = dataPaths;
+ myTargetsState = targetsState;
+ mySrcToFormMap = new OneToManyPathsMapping(new File(getSourceToFormsRoot(), "data"));
+ myMappings = new Mappings(getMappingsRoot(), useMemoryTempCaches);
+ myVersionFile = new File(myDataPaths.getDataStorageRoot(), "version.dat");
+ }
+
+ public SourceToOutputMapping getSourceToOutputMap(final BuildTarget<?> target) throws IOException {
+ SourceToOutputMappingImpl mapping;
+ synchronized (mySourceToOutputLock) {
+ mapping = mySourceToOutputs.get(target);
+ if (mapping == null) {
+ mapping = new SourceToOutputMappingImpl(new File(getSourceToOutputMapRoot(target), "data"));
+ mySourceToOutputs.put(target, mapping);
+ }
+ }
+ return mapping;
+ }
+
+ private File getSourceToOutputMapRoot(BuildTarget<?> target) {
+ return new File(myDataPaths.getTargetDataRoot(target), "src-out");
+ }
+
+ @NotNull
+ public <S extends StorageOwner> S getStorage(@NotNull BuildTarget<?> target, @NotNull StorageProvider<S> provider) throws IOException {
+ synchronized (myTargetStoragesLock) {
+ BuildTargetStorages storages = myTargetStorages.get(target);
+ if (storages == null) {
+ storages = new BuildTargetStorages(target, myDataPaths);
+ myTargetStorages.put(target, storages);
+ }
+ return storages.getOrCreateStorage(provider);
+ }
+ }
+
+ public OneToManyPathsMapping getSourceToFormMap() {
+ return mySrcToFormMap;
+ }
+
+ public Mappings getMappings() {
+ return myMappings;
+ }
+
+ public void cleanTargetStorages(BuildTarget<?> target) throws IOException {
+ try {
+ synchronized (myTargetStoragesLock) {
+ BuildTargetStorages storages = myTargetStorages.remove(target);
+ if (storages != null) {
+ storages.close();
+ }
+ }
+ }
+ finally {
+ // delete all data except src-out mapping which is cleaned in a special way
+ final File[] targetData = myDataPaths.getTargetDataRoot(target).listFiles();
+ if (targetData != null) {
+ final File srcOutputMapRoot = getSourceToOutputMapRoot(target);
+ for (File dataFile : targetData) {
+ if (!FileUtil.filesEqual(dataFile, srcOutputMapRoot)) {
+ FileUtil.delete(dataFile);
+ }
+ }
+ }
+ }
+ }
+
+ public void clean() throws IOException {
+ try {
+ synchronized (myTargetStoragesLock) {
+ myTargetStoragesOwner.close();
+ myTargetStorages.clear();
+ }
+ }
+ finally {
+ try {
+ synchronized (mySourceToOutputLock) {
+ closeSourceToOutputStorages();
+ }
+ }
+ finally {
+ try {
+ wipeStorage(getSourceToFormsRoot(), mySrcToFormMap);
+ }
+ finally {
+ final Mappings mappings = myMappings;
+ if (mappings != null) {
+ synchronized (mappings) {
+ mappings.clean();
+ }
+ }
+ else {
+ FileUtil.delete(getMappingsRoot());
+ }
+ }
+ }
+ myTargetsState.clean();
+ }
+ saveVersion();
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ synchronized (myTargetStoragesLock) {
+ myTargetStoragesOwner.flush(memoryCachesOnly);
+ }
+ synchronized (mySourceToOutputLock) {
+ for (SourceToOutputMappingImpl mapping : mySourceToOutputs.values()) {
+ mapping.flush(memoryCachesOnly);
+ }
+ }
+ mySrcToFormMap.flush(memoryCachesOnly);
+ final Mappings mappings = myMappings;
+ if (mappings != null) {
+ synchronized (mappings) {
+ mappings.flush(memoryCachesOnly);
+ }
+ }
+ }
+
+ public void close() throws IOException {
+ try {
+ myTargetsState.save();
+ synchronized (myTargetStoragesLock) {
+ try {
+ myTargetStoragesOwner.close();
+ }
+ finally {
+ myTargetStorages.clear();
+ }
+ }
+ }
+ finally {
+ try {
+ synchronized (mySourceToOutputLock) {
+ closeSourceToOutputStorages();
+ }
+ }
+ finally {
+ try {
+ closeStorage(mySrcToFormMap);
+ }
+ finally {
+ final Mappings mappings = myMappings;
+ if (mappings != null) {
+ try {
+ mappings.close();
+ }
+ catch (RuntimeException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw ((IOException)cause);
+ }
+ throw e;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void closeSourceToOutputStorages(Collection<BuildTargetChunk> chunks) throws IOException {
+ synchronized (mySourceToOutputLock) {
+ for (BuildTargetChunk chunk : chunks) {
+ for (BuildTarget<?> target : chunk.getTargets()) {
+ final SourceToOutputMappingImpl mapping = mySourceToOutputs.remove(target);
+ if (mapping != null) {
+ mapping.close();
+ }
+ }
+ }
+ }
+ }
+
+ private void closeSourceToOutputStorages() throws IOException {
+ IOException ex = null;
+ try {
+ for (SourceToOutputMappingImpl mapping : mySourceToOutputs.values()) {
+ try {
+ mapping.close();
+ }
+ catch (IOException e) {
+ if (e != null) {
+ ex = e;
+ }
+ }
+ }
+ }
+ finally {
+ mySourceToOutputs.clear();
+ }
+ if (ex != null) {
+ throw ex;
+ }
+ }
+
+ private File getSourceToFormsRoot() {
+ return new File(myDataPaths.getDataStorageRoot(), SRC_TO_FORM_STORAGE);
+ }
+
+ private File getMappingsRoot() {
+ return new File(myDataPaths.getDataStorageRoot(), MAPPINGS_STORAGE);
+ }
+
+ public BuildDataPaths getDataPaths() {
+ return myDataPaths;
+ }
+
+ private static void wipeStorage(File root, @Nullable AbstractStateStorage<?, ?> storage) {
+ if (storage != null) {
+ synchronized (storage) {
+ storage.wipe();
+ }
+ }
+ else {
+ FileUtil.delete(root);
+ }
+ }
+
+ private static void closeStorage(@Nullable AbstractStateStorage<?, ?> storage) throws IOException {
+ if (storage != null) {
+ synchronized (storage) {
+ storage.close();
+ }
+ }
+ }
+
+ private Boolean myVersionDiffers = null;
+
+ public boolean versionDiffers() {
+ final Boolean cached = myVersionDiffers;
+ if (cached != null) {
+ return cached;
+ }
+ try {
+ final DataInputStream is = new DataInputStream(new FileInputStream(myVersionFile));
+ try {
+ final boolean diff = is.readInt() != VERSION;
+ myVersionDiffers = diff;
+ return diff;
+ }
+ finally {
+ is.close();
+ }
+ }
+ catch (FileNotFoundException ignored) {
+ return false; // treat it as a new dir
+ }
+ catch (IOException ex) {
+ LOG.info(ex);
+ }
+ return true;
+ }
+
+ public void saveVersion() {
+ final Boolean differs = myVersionDiffers;
+ if (differs == null || differs) {
+ try {
+ FileUtil.createIfDoesntExist(myVersionFile);
+ final DataOutputStream os = new DataOutputStream(new FileOutputStream(myVersionFile));
+ try {
+ os.writeInt(VERSION);
+ myVersionDiffers = Boolean.FALSE;
+ }
+ finally {
+ os.close();
+ }
+ }
+ catch (IOException ignored) {
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java
new file mode 100644
index 000000000000..1ed0edbb1bc8
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SmartList;
+import gnu.trove.THashSet;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class BuildTargetConfiguration {
+ private static final Logger LOG = Logger.getInstance(BuildTargetConfiguration.class);
+ private final BuildTarget<?> myTarget;
+ private final BuildTargetsState myTargetsState;
+ private String myConfiguration;
+ private volatile String myCurrentState;
+
+ public BuildTargetConfiguration(BuildTarget<?> target, BuildTargetsState targetsState) {
+ myTarget = target;
+ myTargetsState = targetsState;
+ myConfiguration = load();
+ }
+
+ private String load() {
+ File configFile = getConfigFile();
+ if (configFile.exists()) {
+ try {
+ return new String(FileUtil.loadFileText(configFile));
+ }
+ catch (IOException e) {
+ LOG.info("Cannot load configuration of " + myTarget);
+ }
+ }
+ return "";
+ }
+
+ public boolean isTargetDirty() {
+ final String currentState = getCurrentState();
+ if (!currentState.equals(myConfiguration)) {
+ LOG.debug(myTarget + " configuration was changed:");
+ LOG.debug("Old:");
+ LOG.debug(myConfiguration);
+ LOG.debug("New:");
+ LOG.debug(currentState);
+ LOG.debug(myTarget + " will be recompiled");
+ return true;
+ }
+ return false;
+ }
+
+ public void save() {
+ try {
+ File configFile = getConfigFile();
+ FileUtil.createParentDirs(configFile);
+ Writer out = new BufferedWriter(new FileWriter(configFile));
+ try {
+ String current = getCurrentState();
+ out.write(current);
+ myConfiguration = current;
+ }
+ finally {
+ out.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info("Cannot save configuration of " + myConfiguration, e);
+ }
+ }
+
+ private File getConfigFile() {
+ return new File(myTargetsState.getDataPaths().getTargetDataRoot(myTarget), "config.dat");
+ }
+
+ private File getNonexistentOutputsFile() {
+ return new File(myTargetsState.getDataPaths().getTargetDataRoot(myTarget), "nonexistent-outputs.dat");
+ }
+
+ private String getCurrentState() {
+ String state = myCurrentState;
+ if (state == null) {
+ myCurrentState = state = saveToString();
+ }
+ return state;
+ }
+
+ private String saveToString() {
+ StringWriter out = new StringWriter();
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ myTarget.writeConfiguration(new PrintWriter(out), myTargetsState.getDataPaths(), myTargetsState.getBuildRootIndex());
+ return out.toString();
+ }
+
+ public void storeNonexistentOutputRoots(CompileContext context) throws IOException {
+ Collection<File> outputRoots = myTarget.getOutputRoots(context);
+ List<String> nonexistentOutputRoots = new SmartList<String>();
+ for (File root : outputRoots) {
+ if (!root.exists()) {
+ nonexistentOutputRoots.add(root.getAbsolutePath());
+ }
+ }
+ File file = getNonexistentOutputsFile();
+ if (nonexistentOutputRoots.isEmpty()) {
+ if (file.exists()) {
+ FileUtil.delete(file);
+ }
+ }
+ else {
+ FileUtil.writeToFile(file, StringUtil.join(nonexistentOutputRoots, "\n"));
+ }
+ }
+
+ public boolean outputRootWasDeleted(CompileContext context) throws IOException {
+ List<String> nonexistentOutputRoots = new SmartList<String>();
+ for (File outputRoot : myTarget.getOutputRoots(context)) {
+ if (!outputRoot.exists()) {
+ nonexistentOutputRoots.add(outputRoot.getAbsolutePath());
+ }
+ }
+ if (nonexistentOutputRoots.isEmpty()) return false;
+
+ Set<String> storedNonExistentOutputs;
+ File file = getNonexistentOutputsFile();
+ if (!file.exists()) {
+ storedNonExistentOutputs = Collections.emptySet();
+ }
+ else {
+ List<String> lines = StringUtil.split(FileUtil.loadFile(file), "\n");
+ storedNonExistentOutputs = new THashSet<String>(lines, FileUtil.PATH_HASHING_STRATEGY);
+ }
+ return !storedNonExistentOutputs.containsAll(nonexistentOutputRoots);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java
new file mode 100644
index 000000000000..e9e2291a166a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.io.IOUtil;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author nik
+ */
+public class BuildTargetTypeState {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildTargetTypeState");
+ private final Map<BuildTarget<?>, Integer> myTargetIds;
+ private final ConcurrentMap<BuildTarget<?>, BuildTargetConfiguration> myConfigurations;
+ private final BuildTargetType<?> myTargetType;
+ private final BuildTargetsState myTargetsState;
+ private final File myTargetsFile;
+
+ public BuildTargetTypeState(BuildTargetType<?> targetType, BuildTargetsState state) {
+ myTargetType = targetType;
+ myTargetsState = state;
+ myTargetsFile = new File(state.getDataPaths().getTargetTypeDataRoot(targetType), "targets.dat");
+ myConfigurations = new ConcurrentHashMap<BuildTarget<?>, BuildTargetConfiguration>();
+ myTargetIds = new HashMap<BuildTarget<?>, Integer>();
+ load();
+ }
+
+ private boolean load() {
+ if (!myTargetsFile.exists()) {
+ return false;
+ }
+
+ try {
+ DataInputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream(myTargetsFile)));
+ try {
+ input.readInt();//reserved for version
+ int size = input.readInt();
+ BuildTargetLoader<?> loader = myTargetType.createLoader(myTargetsState.getModel());
+ while (size-- > 0) {
+ String stringId = IOUtil.readString(input);
+ int intId = input.readInt();
+ myTargetsState.markUsedId(intId);
+ BuildTarget<?> target = loader.createTarget(stringId);
+ if (target != null) {
+ myTargetIds.put(target, intId);
+ }
+ else {
+ LOG.info("Unknown " + myTargetType.getTypeId() + " target: " + stringId);
+ }
+ }
+ return true;
+ }
+ finally {
+ input.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info("Cannot load " + myTargetType.getTypeId() + " targets data: " + e.getMessage(), e);
+ return false;
+ }
+ }
+
+ public synchronized void save() {
+ try {
+ FileUtil.createParentDirs(myTargetsFile);
+ DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(myTargetsFile)));
+ try {
+ output.writeInt(0);
+ output.writeInt(myTargetIds.size());
+ for (Map.Entry<BuildTarget<?>, Integer> entry : myTargetIds.entrySet()) {
+ IOUtil.writeString(entry.getKey().getId(), output);
+ output.writeInt(entry.getValue());
+ }
+ }
+ finally {
+ output.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info("Cannot save " + myTargetType.getTypeId() + " targets data: " + e.getMessage(), e);
+ }
+ }
+
+ public synchronized int getTargetId(BuildTarget<?> target) {
+ if (!myTargetIds.containsKey(target)) {
+ myTargetIds.put(target, myTargetsState.getFreeId());
+ }
+ return myTargetIds.get(target);
+ }
+
+ public BuildTargetConfiguration getConfiguration(BuildTarget<?> target) {
+ BuildTargetConfiguration configuration = myConfigurations.get(target);
+ if (configuration == null) {
+ configuration = new BuildTargetConfiguration(target, myTargetsState);
+ myConfigurations.putIfAbsent(target, configuration);
+ configuration = myConfigurations.get(target);
+ }
+ return configuration;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java
new file mode 100644
index 000000000000..2c95168fc29d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ConcurrentHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.*;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author nik
+ */
+public class BuildTargetsState {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildTargetsState");
+ private final BuildDataPaths myDataPaths;
+ private AtomicInteger myMaxTargetId = new AtomicInteger(0);
+ private ConcurrentMap<BuildTargetType<?>, BuildTargetTypeState> myTypeStates = new ConcurrentHashMap<BuildTargetType<?>, BuildTargetTypeState>();
+ private JpsModel myModel;
+ private final BuildRootIndexImpl myBuildRootIndex;
+
+ public BuildTargetsState(BuildDataPaths dataPaths, JpsModel model, BuildRootIndexImpl buildRootIndex) {
+ myDataPaths = dataPaths;
+ myModel = model;
+ myBuildRootIndex = buildRootIndex;
+ File targetTypesFile = getTargetTypesFile();
+ try {
+ DataInputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream(targetTypesFile)));
+ try {
+ myMaxTargetId.set(input.readInt());
+ }
+ finally {
+ input.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.debug("Cannot load " + targetTypesFile + ":" + e.getMessage(), e);
+ LOG.debug("Loading all target types to calculate max target id");
+ for (BuildTargetType<?> type : BuilderRegistry.getInstance().getTargetTypes()) {
+ getTypeState(type);
+ }
+ }
+ }
+
+ private File getTargetTypesFile() {
+ return new File(myDataPaths.getTargetsDataRoot(), "targetTypes.dat");
+ }
+
+ public void save() {
+ try {
+ File targetTypesFile = getTargetTypesFile();
+ FileUtil.createParentDirs(targetTypesFile);
+ DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(targetTypesFile)));
+ try {
+ output.writeInt(myMaxTargetId.get());
+ }
+ finally {
+ output.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info("Cannot save targets info: " + e.getMessage(), e);
+ }
+ for (BuildTargetTypeState state : myTypeStates.values()) {
+ state.save();
+ }
+ }
+
+ public int getBuildTargetId(@NotNull BuildTarget<?> target) {
+ return getTypeState(target.getTargetType()).getTargetId(target);
+ }
+
+ public BuildTargetConfiguration getTargetConfiguration(@NotNull BuildTarget<?> target) {
+ return getTypeState(target.getTargetType()).getConfiguration(target);
+ }
+
+ private BuildTargetTypeState getTypeState(BuildTargetType<?> type) {
+ BuildTargetTypeState state = myTypeStates.get(type);
+ if (state == null) {
+ state = new BuildTargetTypeState(type, this);
+ myTypeStates.putIfAbsent(type, state);
+ state = myTypeStates.get(type);
+ }
+ return state;
+ }
+
+ public void markUsedId(int id) {
+ int current;
+ int max;
+ do {
+ current = myMaxTargetId.get();
+ max = Math.max(id, current);
+ }
+ while (!myMaxTargetId.compareAndSet(current, max));
+ }
+
+ public int getFreeId() {
+ return myMaxTargetId.incrementAndGet();
+ }
+
+ public void clean() {
+ FileUtil.delete(myDataPaths.getTargetsDataRoot());
+ }
+
+ public JpsModel getModel() {
+ return myModel;
+ }
+
+ public BuildRootIndexImpl getBuildRootIndex() {
+ return myBuildRootIndex;
+ }
+
+ public BuildDataPaths getDataPaths() {
+ return myDataPaths;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/CompositeStorageOwner.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/CompositeStorageOwner.java
new file mode 100644
index 000000000000..23100f56f989
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/CompositeStorageOwner.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public abstract class CompositeStorageOwner implements StorageOwner {
+ protected abstract Iterable<? extends StorageOwner> getChildStorages();
+
+ @Override
+ public void flush(boolean memoryCachesOnly) {
+ for (StorageOwner child : getChildStorages()) {
+ if (child != null) {
+ child.flush(memoryCachesOnly);
+ }
+ }
+ }
+
+ @Override
+ public void clean() throws IOException {
+ IOException exc = null;
+ for (StorageOwner child : getChildStorages()) {
+ if (child != null) {
+ try {
+ child.clean();
+ }
+ catch (IOException e) {
+ exc = e;
+ }
+ }
+ }
+ if (exc != null) {
+ throw exc;
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ IOException exc = null;
+ for (StorageOwner child : getChildStorages()) {
+ if (child != null) {
+ try {
+ child.close();
+ }
+ catch (IOException e) {
+ exc = e;
+ }
+ }
+ }
+ if (exc != null) {
+ throw exc;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java
new file mode 100644
index 000000000000..f467dd27c929
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.IOUtil;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 9/10/12
+*/
+public final class FileKeyDescriptor implements KeyDescriptor<File> {
+ private final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
+
+ public void save(DataOutput out, File value) throws IOException {
+ IOUtil.writeUTFFast(buffer, out, value.getPath());
+ }
+
+ public File read(DataInput in) throws IOException {
+ return new File(IOUtil.readUTFFast(buffer, in));
+ }
+
+ public int getHashCode(File value) {
+ return FileUtil.fileHashCode(value);
+ }
+
+ public boolean isEqual(File val1, File val2) {
+ return FileUtil.filesEqual(val1, val2);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ModuleOutputRootsLayout.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ModuleOutputRootsLayout.java
new file mode 100644
index 000000000000..d5d31457d512
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ModuleOutputRootsLayout.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.IOUtil;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 12/29/11
+ */
+public class ModuleOutputRootsLayout extends AbstractStateStorage<String, Pair<String, String>>{
+
+ public ModuleOutputRootsLayout(File storePath) throws IOException {
+ super(storePath, new EnumeratorStringDescriptor(), new PairDataExternalizer());
+ }
+
+ public void appendData(String s, Pair<String, String> data) throws IOException {
+ update(s, data);
+ }
+
+ private static class PairDataExternalizer implements DataExternalizer<Pair<String, String>> {
+ public void save(DataOutput out, Pair<String, String> value) throws IOException {
+ IOUtil.writeString(value.getFirst(), out);
+ IOUtil.writeString(value.getSecond(), out);
+ }
+
+ public Pair<String, String> read(DataInput in) throws IOException {
+ final String first = IOUtil.readString(in);
+ final String second = IOUtil.readString(in);
+ return new Pair<String, String>(first, second);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java
new file mode 100644
index 000000000000..5271f038b12b
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.IOUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/11/12
+ */
+public class OneToManyPathsMapping extends AbstractStateStorage<String, Collection<String>> {
+ public OneToManyPathsMapping(File storePath) throws IOException {
+ super(storePath, new PathStringDescriptor(), new PathCollectionExternalizer());
+ }
+
+ @Override
+ public void update(@NotNull String keyPath, @NotNull Collection<String> boundPaths) throws IOException {
+ super.update(FileUtil.toSystemIndependentName(keyPath), normalizePaths(boundPaths));
+ }
+
+ public final void update(@NotNull String keyPath, @NotNull String boundPath) throws IOException {
+ super.update(FileUtil.toSystemIndependentName(keyPath), Collections.singleton(FileUtil.toSystemIndependentName(boundPath)));
+ }
+
+ public final void appendData(@NotNull String keyPath, @NotNull String boundPath) throws IOException {
+ super.appendData(FileUtil.toSystemIndependentName(keyPath), Collections.singleton(FileUtil.toSystemIndependentName(boundPath)));
+ }
+
+ @Override
+ public void appendData(@NotNull String keyPath, @NotNull Collection<String> boundPaths) throws IOException {
+ super.appendData(FileUtil.toSystemIndependentName(keyPath), normalizePaths(boundPaths));
+ }
+
+ @Nullable
+ @Override
+ public Collection<String> getState(@NotNull String keyPath) throws IOException {
+ return super.getState(FileUtil.toSystemIndependentName(keyPath));
+ }
+
+ @Override
+ public void remove(@NotNull String keyPath) throws IOException {
+ super.remove(FileUtil.toSystemIndependentName(keyPath));
+ }
+
+ public final void removeData(@NotNull String keyPath, @NotNull String boundPath) throws IOException {
+ final Collection<String> outputPaths = getState(FileUtil.toSystemIndependentName(keyPath));
+ if (outputPaths != null) {
+ final boolean removed = outputPaths.remove(FileUtil.toSystemIndependentName(boundPath));
+ if (outputPaths.isEmpty()) {
+ remove(keyPath);
+ }
+ else {
+ if (removed) {
+ update(keyPath, outputPaths);
+ }
+ }
+ }
+ }
+
+ private static class PathCollectionExternalizer implements DataExternalizer<Collection<String>> {
+ public void save(DataOutput out, Collection<String> value) throws IOException {
+ for (String str : value) {
+ IOUtil.writeString(str, out);
+ }
+ }
+
+ public Collection<String> read(DataInput in) throws IOException {
+ final Set<String> result = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ final DataInputStream stream = (DataInputStream)in;
+ while (stream.available() > 0) {
+ final String str = IOUtil.readString(stream);
+ result.add(str);
+ }
+ return result;
+ }
+ }
+
+ private static Collection<String> normalizePaths(Collection<String> outputs) {
+ Collection<String> normalized = new ArrayList<String>(outputs.size());
+ for (String out : outputs) {
+ normalized.add(FileUtil.toSystemIndependentName(out));
+ }
+ return normalized;
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java
new file mode 100644
index 000000000000..2180ef6e928e
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+
+/**
+* @author nik
+*/
+public class PathStringDescriptor extends EnumeratorStringDescriptor {
+ @Override
+ public int getHashCode(String value) {
+ return FileUtil.pathHashCode(value);
+ }
+
+ @Override
+ public boolean isEqual(String val1, String val2) {
+ return FileUtil.pathsEqual(val1, val2);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ProjectTimestamps.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ProjectTimestamps.java
new file mode 100644
index 000000000000..dac27d875253
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ProjectTimestamps.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/7/11
+ */
+public class ProjectTimestamps {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.ProjectTimestamps");
+ private static final String TIMESTAMP_STORAGE = "timestamps";
+ private final TimestampStorage myTimestamps;
+ private final File myTimestampsRoot;
+
+ public ProjectTimestamps(final File dataStorageRoot, BuildTargetsState targetsState) throws IOException {
+ myTimestampsRoot = new File(dataStorageRoot, TIMESTAMP_STORAGE);
+ myTimestamps = new TimestampStorage(new File(myTimestampsRoot, "data"), targetsState);
+ }
+
+ public TimestampStorage getStorage() {
+ return myTimestamps;
+ }
+
+ public void clean() throws IOException {
+ final TimestampStorage timestamps = myTimestamps;
+ if (timestamps != null) {
+ timestamps.wipe();
+ }
+ else {
+ FileUtil.delete(myTimestampsRoot);
+ }
+ }
+
+ public void close() {
+ final TimestampStorage timestamps = myTimestamps;
+ if (timestamps != null) {
+ try {
+ timestamps.close();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ FileUtil.delete(myTimestampsRoot);
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java
new file mode 100644
index 000000000000..9518d5b540f9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/11/12
+ */
+public class SourceToOutputMappingImpl implements SourceToOutputMapping {
+ private final OneToManyPathsMapping myMapping;
+
+ public SourceToOutputMappingImpl(File storePath) throws IOException {
+ myMapping = new OneToManyPathsMapping(storePath);
+ }
+
+ @Override
+ public void setOutputs(@NotNull String srcPath, @NotNull Collection<String> outputs) throws IOException {
+ myMapping.update(srcPath, outputs);
+ }
+
+ @Override
+ public void setOutput(@NotNull String srcPath, @NotNull String outputPath) throws IOException {
+ myMapping.update(srcPath, outputPath);
+ }
+
+ @Override
+ public void appendOutput(@NotNull String srcPath, @NotNull String outputPath) throws IOException {
+ myMapping.appendData(srcPath, outputPath);
+ }
+
+ @Override
+ public void remove(@NotNull String srcPath) throws IOException {
+ myMapping.remove(srcPath);
+ }
+
+ @Override
+ public void removeOutput(@NotNull String sourcePath, @NotNull String outputPath) throws IOException {
+ myMapping.removeData(sourcePath, outputPath);
+ }
+
+ @NotNull
+ @Override
+ public Collection<String> getSources() throws IOException {
+ return myMapping.getKeys();
+ }
+
+ @Nullable
+ @Override
+ public Collection<String> getOutputs(@NotNull String srcPath) throws IOException {
+ return myMapping.getState(srcPath);
+ }
+
+ @NotNull
+ @Override
+ public Iterator<String> getSourcesIterator() throws IOException {
+ return myMapping.getKeysIterator();
+ }
+
+ public void flush(boolean memoryCachesOnly) {
+ myMapping.flush(memoryCachesOnly);
+ }
+
+ public void close() throws IOException {
+ myMapping.close();
+ }
+
+ public void clean() throws IOException {
+ myMapping.clean();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/StorageOwner.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/StorageOwner.java
new file mode 100644
index 000000000000..adac109185da
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/StorageOwner.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public interface StorageOwner {
+ void flush(boolean memoryCachesOnly);
+ void clean() throws IOException;
+ void close() throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java
new file mode 100644
index 000000000000..9955c6a64c83
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTarget;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 10/7/11
+ */
+public class TimestampStorage extends AbstractStateStorage<File, TimestampStorage.TimestampPerTarget[]> implements Timestamps {
+ private final BuildTargetsState myTargetsState;
+
+ public TimestampStorage(File storePath, BuildTargetsState targetsState) throws IOException {
+ super(storePath, new FileKeyDescriptor(), new StateExternalizer());
+ myTargetsState = targetsState;
+ }
+
+ @Override
+ public void force() {
+ super.force();
+ }
+
+ @Override
+ public void clean() throws IOException {
+ super.clean();
+ }
+
+ @Override
+ public long getStamp(File file, BuildTarget<?> target) throws IOException {
+ final TimestampPerTarget[] state = getState(file);
+ if (state != null) {
+ int targetId = myTargetsState.getBuildTargetId(target);
+ for (TimestampPerTarget timestampPerTarget : state) {
+ if (timestampPerTarget.targetId == targetId) {
+ return timestampPerTarget.timestamp;
+ }
+ }
+ }
+ return -1L;
+ }
+
+ @Override
+ public void saveStamp(File file, BuildTarget<?> buildTarget, long timestamp) throws IOException {
+ int targetId = myTargetsState.getBuildTargetId(buildTarget);
+ update(file, updateTimestamp(getState(file), targetId, timestamp));
+ }
+
+ @NotNull
+ private static TimestampPerTarget[] updateTimestamp(TimestampPerTarget[] oldState, final int targetId, long timestamp) {
+ final TimestampPerTarget newItem = new TimestampPerTarget(targetId, timestamp);
+ if (oldState == null) {
+ return new TimestampPerTarget[]{newItem};
+ }
+ for (int i = 0, length = oldState.length; i < length; i++) {
+ if (oldState[i].targetId == targetId) {
+ oldState[i] = newItem;
+ return oldState;
+ }
+ }
+ return ArrayUtil.append(oldState, newItem);
+ }
+
+ public void removeStamp(File file, BuildTarget<?> buildTarget) throws IOException {
+ TimestampPerTarget[] state = getState(file);
+ if (state != null) {
+ int targetId = myTargetsState.getBuildTargetId(buildTarget);
+ for (int i = 0; i < state.length; i++) {
+ TimestampPerTarget timestampPerTarget = state[i];
+ if (timestampPerTarget.targetId == targetId) {
+ if (state.length == 1) {
+ remove(file);
+ }
+ else {
+ TimestampPerTarget[] newState = ArrayUtil.remove(state, i);
+ update(file, newState);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public static class TimestampPerTarget {
+ public final int targetId;
+ public final long timestamp;
+
+ public TimestampPerTarget(int targetId, long timestamp) {
+ this.targetId = targetId;
+ this.timestamp = timestamp;
+ }
+ }
+
+ private static class StateExternalizer implements DataExternalizer<TimestampPerTarget[]> {
+ public void save(DataOutput out, TimestampPerTarget[] value) throws IOException {
+ out.writeInt(value.length);
+ for (TimestampPerTarget target : value) {
+ out.writeInt(target.targetId);
+ out.writeLong(target.timestamp);
+ }
+ }
+
+ public TimestampPerTarget[] read(DataInput in) throws IOException {
+ int size = in.readInt();
+ TimestampPerTarget[] targets = new TimestampPerTarget[size];
+ for (int i = 0; i < size; i++) {
+ int id = in.readInt();
+ long timestamp = in.readLong();
+ targets[i] = new TimestampPerTarget(id, timestamp);
+ }
+ return targets;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampValidityState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampValidityState.java
new file mode 100644
index 000000000000..6ea93871f979
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampValidityState.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * A simple implementation of ValidityState that is enough for most cases.
+ * The file is considered modified if its timestamp is changed.
+ */
+public final class TimestampValidityState implements ValidityState {
+ private final long myTimestamp;
+
+ /**
+ * Loads the validity state from the specified stream.
+ *
+ * @param is the stream to load the validity state from.
+ * @throws IOException if the stream read fails.
+ */
+ public TimestampValidityState(DataInput is) throws IOException{
+ myTimestamp = is.readLong();
+ }
+
+ /**
+ * Creates a validity state with the specified timestamp.
+ *
+ * @param timestamp the timestamp for the validity state.
+ */
+ public TimestampValidityState(long timestamp) {
+ myTimestamp = timestamp;
+ }
+
+ public long getTimestamp() {
+ return myTimestamp;
+ }
+
+ public boolean equalsTo(ValidityState otherState) {
+ return otherState instanceof TimestampValidityState && myTimestamp == ((TimestampValidityState)otherState).myTimestamp;
+ }
+
+ /**
+ * Saves the validity state to the specified stream.
+ *
+ * @param out
+ * @throws java.io.IOException if the stream write fails.
+ */
+ public void save(DataOutput out) throws IOException {
+ out.writeLong(myTimestamp);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/Timestamps.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/Timestamps.java
new file mode 100644
index 000000000000..39fe14777c7a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/Timestamps.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import org.jetbrains.jps.builders.BuildTarget;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 4/24/12
+ */
+public interface Timestamps {
+ void force();
+
+ void saveStamp(File file, BuildTarget<?> buildTarget, long timestamp) throws IOException;
+
+ void removeStamp(File file, BuildTarget<?> buildTarget) throws IOException;
+
+ void clean() throws IOException;
+
+ long getStamp(File file, BuildTarget<?> target) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ValidityState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ValidityState.java
new file mode 100644
index 000000000000..816c755d31e1
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/ValidityState.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.storage;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * Instances of this class are associated with the files processed by compilers.
+ * A file is considered modified if currently associated ValidityState differs from the previously stored ValiditySate for this file.
+ */
+public interface ValidityState {
+ /**
+ * Compares this validity state to other ValidityState.
+ *
+ * @param otherState the state to compare with.
+ * @return true if states can be considered equal, false otherwise.
+ */
+ boolean equalsTo(ValidityState otherState);
+ /**
+ * Invoked by make subsystem in order to store the state.
+ *
+ * @param out the output to which the state should be stored.
+ * @throws java.io.IOException if the save operation failed because of an I/O error.
+ */
+ void save(DataOutput out) throws IOException;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/indices/IgnoredFileIndex.java b/jps/jps-builders/src/org/jetbrains/jps/indices/IgnoredFileIndex.java
new file mode 100644
index 000000000000..cddd4a4e9852
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/indices/IgnoredFileIndex.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.indices;
+
+/**
+ * @author nik
+ */
+public interface IgnoredFileIndex {
+ boolean isIgnored(String fileName);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/indices/ModuleExcludeIndex.java b/jps/jps-builders/src/org/jetbrains/jps/indices/ModuleExcludeIndex.java
new file mode 100644
index 000000000000..c0d1b5401d8f
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/indices/ModuleExcludeIndex.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.indices;
+
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface ModuleExcludeIndex {
+ boolean isExcluded(File file);
+
+ Collection<File> getModuleExcludes(JpsModule module);
+
+ boolean isInContent(File file);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java
new file mode 100644
index 000000000000..fec3e344ed37
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.indices.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * @author nik
+ */
+public class IgnoredFileIndexImpl implements IgnoredFileIndex {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.IgnoredFilePatterns");
+ private List<Pattern> myPatterns = new ArrayList<Pattern>();
+
+ public IgnoredFileIndexImpl(JpsModel model) {
+ loadFromString(model.getGlobal().getFileTypesConfiguration().getIgnoredPatternString());
+ }
+
+ private void loadFromString(String patterns) {
+ myPatterns.clear();
+ StringTokenizer tokenizer = new StringTokenizer(patterns, ";");
+ while (tokenizer.hasMoreTokens()) {
+ String pattern = tokenizer.nextToken();
+ if (!StringUtil.isEmptyOrSpaces(pattern)) {
+ try {
+ myPatterns.add(Pattern.compile(convertToJavaPattern(pattern)));
+ }
+ catch (PatternSyntaxException e) {
+ LOG.info("Cannot load ignored file pattern " + pattern, e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isIgnored(String fileName) {
+ for (Pattern pattern : myPatterns) {
+ if (pattern.matcher(fileName).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static String convertToJavaPattern(String wildcardPattern) {
+ wildcardPattern = StringUtil.replace(wildcardPattern, ".", "\\.");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "*?", ".+");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "?*", ".+");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "*", ".*");
+ wildcardPattern = StringUtil.replace(wildcardPattern, "?", ".");
+ return wildcardPattern;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/indices/impl/ModuleExcludeIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/ModuleExcludeIndexImpl.java
new file mode 100644
index 000000000000..28c1717caf28
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/ModuleExcludeIndexImpl.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.indices.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
+import org.jetbrains.jps.model.java.JpsJavaProjectExtension;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/11/12
+ */
+public class ModuleExcludeIndexImpl implements ModuleExcludeIndex {
+ private final Set<File> myExcludedRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ private final Set<File> myContentRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ private final Map<JpsModule, List<File>> myModuleToExcludesMap = new THashMap<JpsModule, List<File>>();
+
+ public ModuleExcludeIndexImpl(JpsModel model) {
+ final Collection<JpsModule> allModules = model.getProject().getModules();
+ for (final JpsModule module : allModules) {
+ final List<File> moduleExcludes = new ArrayList<File>();
+ for (String url : module.getExcludeRootsList().getUrls()) {
+ moduleExcludes.add(JpsPathUtil.urlToFile(url));
+ }
+ JpsJavaModuleExtension moduleExtension = JpsJavaExtensionService.getInstance().getModuleExtension(module);
+ if (moduleExtension != null && !moduleExtension.isInheritOutput() && moduleExtension.isExcludeOutput()) {
+ String outputUrl = moduleExtension.getOutputUrl();
+ if (outputUrl != null) {
+ moduleExcludes.add(JpsPathUtil.urlToFile(outputUrl));
+ }
+ String testOutputUrl = moduleExtension.getTestOutputUrl();
+ if (testOutputUrl != null) {
+ moduleExcludes.add(JpsPathUtil.urlToFile(testOutputUrl));
+ }
+ }
+ myModuleToExcludesMap.put(module, moduleExcludes);
+ myExcludedRoots.addAll(moduleExcludes);
+ }
+
+ Map<File, JpsModule> contentToModule = new THashMap<File, JpsModule>(FileUtil.FILE_HASHING_STRATEGY);
+ for (JpsModule module : allModules) {
+ for (String contentUrl : module.getContentRootsList().getUrls()) {
+ File contentRoot = JpsPathUtil.urlToFile(contentUrl);
+ contentToModule.put(contentRoot, module);
+ }
+ }
+ List<File> parents = new ArrayList<File>();
+ for (JpsModule module : allModules) {
+ for (String contentUrl : module.getContentRootsList().getUrls()) {
+ File contentRoot = JpsPathUtil.urlToFile(contentUrl);
+ File parent = contentRoot.getParentFile();
+ JpsModule parentModule = null;
+ parents.clear();
+ while (parent != null) {
+ parents.add(parent);
+ if (contentToModule.containsKey(parent)) {
+ parentModule = contentToModule.get(parent);
+ break;
+ }
+ parent = parent.getParentFile();
+ }
+ if (parentModule != null) {
+ myModuleToExcludesMap.get(parentModule).add(contentRoot);
+ }
+ else {
+ myContentRoots.add(contentRoot);
+ }
+ for (File file : parents) {
+ contentToModule.put(file, parentModule);
+ }
+ }
+ }
+
+ JpsJavaProjectExtension projectExtension = JpsJavaExtensionService.getInstance().getProjectExtension(model.getProject());
+ if (projectExtension != null) {
+ String url = projectExtension.getOutputUrl();
+ if (!StringUtil.isEmpty(url)) {
+ File excluded = JpsPathUtil.urlToFile(url);
+ File parent = excluded;
+ while (parent != null) {
+ JpsModule module = contentToModule.get(parent);
+ if (module != null) {
+ myModuleToExcludesMap.get(module).add(excluded);
+ }
+ parent = FileUtil.getParentFile(parent);
+ }
+ myExcludedRoots.add(excluded);
+ }
+ }
+
+ for (List<File> files : myModuleToExcludesMap.values()) {
+ ((ArrayList<File>)files).trimToSize();
+ }
+ }
+
+ @Override
+ public boolean isExcluded(File file) {
+ return JpsPathUtil.isUnder(myExcludedRoots, file);
+ }
+
+ @Override
+ public boolean isInContent(File file) {
+ return JpsPathUtil.isUnder(myContentRoots, file);
+ }
+
+ @Override
+ public Collection<File> getModuleExcludes(JpsModule module) {
+ return myModuleToExcludesMap.get(module);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationCanceledException.java b/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationCanceledException.java
new file mode 100644
index 000000000000..b8ba3e0598da
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationCanceledException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 4/2/12
+ */
+class CompilationCanceledException extends RuntimeException{
+ CompilationCanceledException() {
+ super("Compilation canceled");
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java
new file mode 100644
index 000000000000..ee4269248c14
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import javax.tools.*;
+import java.util.Collection;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/22/12
+*/
+public interface DiagnosticOutputConsumer extends DiagnosticListener<JavaFileObject> {
+ void outputLineAvailable(String line);
+ void registerImports(String className, Collection<String> imports, Collection<String> staticImports);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/DummyJavaFileObject.java b/jps/jps-builders/src/org/jetbrains/jps/javac/DummyJavaFileObject.java
new file mode 100644
index 000000000000..3669c9d7f3ec
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/DummyJavaFileObject.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.JavaFileObject;
+import java.io.*;
+import java.net.URI;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/23/12
+*/
+class DummyJavaFileObject implements JavaFileObject {
+ // todo: use proxy to handle possible interface changes?
+ private final URI myUri;
+
+ DummyJavaFileObject(URI uri) {
+ myUri = uri;
+ }
+
+ public Kind getKind() {
+ return Kind.SOURCE;
+ }
+
+ public boolean isNameCompatible(String simpleName, Kind kind) {
+ throw new UnsupportedOperationException();
+ }
+
+ public NestingKind getNestingKind() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Modifier getAccessLevel() {
+ throw new UnsupportedOperationException();
+ }
+
+ public URI toUri() {
+ return myUri;
+ }
+
+ public String getName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public InputStream openInputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public long getLastModified() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean delete() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java
new file mode 100644
index 000000000000..84dfae6e39fa
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.ImportTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 2/1/12
+ *
+ */
+@SupportedAnnotationTypes("*")
+public class JavacASTAnalyser extends AbstractProcessor{
+ private Trees myTrees;
+ private final DiagnosticOutputConsumer myOutputConsumer;
+ private final boolean mySuppressOtherProcessors;
+
+ public JavacASTAnalyser(DiagnosticOutputConsumer outputConsumer, boolean suppressOtherProcessors) {
+ myOutputConsumer = outputConsumer;
+ mySuppressOtherProcessors = suppressOtherProcessors;
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ myTrees = Trees.instance(processingEnv);
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ final Set<? extends Element> elements = roundEnv.getRootElements();
+ for (Element element : elements) {
+ if (!(element instanceof TypeElement)) {
+ continue;
+ }
+ final TypeElement typeElement = (TypeElement)element;
+
+ final ImportsCollector importsCollector = new ImportsCollector();
+ importsCollector.scan(myTrees.getPath(typeElement).getParentPath().getLeaf(), myTrees);
+
+ final Set<String> imports = importsCollector.getImports();
+ final Set<String> staticImports = importsCollector.getStaticImports();
+
+ if (!imports.isEmpty() || !staticImports.isEmpty()) {
+ final String className = typeElement.getQualifiedName().toString();
+ myOutputConsumer.registerImports(className, imports, staticImports);
+ }
+ break;
+ }
+ return mySuppressOtherProcessors;
+ }
+
+ private static class ImportsCollector extends TreeScanner<Object, Trees> {
+ private Set<String> myImports = new HashSet<String>();
+ private Set<String> myStaticImports = new HashSet<String>();
+
+ public Set<String> getImports() {
+ return myImports;
+ }
+
+ public Set<String> getStaticImports() {
+ return myStaticImports;
+ }
+
+ public Object visitImport(ImportTree node, Trees trees) {
+ final Tree identifier = node.getQualifiedIdentifier();
+ final Set<String> container = node.isStatic()? myStaticImports : myImports;
+ container.add(identifier.toString());
+ return null;
+ }
+
+ public Object visitClass(ClassTree node, Trees trees) {
+ return null;
+ }
+
+ //public void registerOverriddenMethod(TypeElement classElement, ExecutableElement method) {
+ // final Elements utils = myProcessingEnvironment.getElementUtils();
+ // final String qName = utils.getBinaryName(classElement).toString();
+ // List<MethodDescriptor> descriptors = myOverriddenMethods.get(qName);
+ // if (descriptors == null) {
+ // descriptors = new ArrayList<MethodDescriptor>();
+ // myOverriddenMethods.put(qName, descriptors);
+ // }
+ // final StringBuilder buf = new StringBuilder();
+ // buf.append("(");
+ // for (VariableElement param : method.getParameters()) {
+ // buf.append(getSignature(param.asType()));
+ // }
+ // buf.append(")").append(getSignature(method.getReturnType()));
+ // descriptors.add(new MethodDescriptor(method.getSimpleName().toString(), buf.toString()));
+ //}
+
+ //private static String getSignature(TypeMirror type) {
+ // switch (type.getKind()) {
+ // case BOOLEAN: return "Z";
+ // case BYTE: return "B";
+ // case CHAR: return "C";
+ // case SHORT: return "S";
+ // case INT: return "I";
+ // case LONG: return "J";
+ // case FLOAT: return "F";
+ // case DOUBLE: return "D";
+ // case VOID: return "V";
+ // case ARRAY:
+ // final String signature = getSignature(((ArrayType)type).getComponentType());
+ // return signature != null? "[" + signature : null;
+ // case DECLARED:
+ // final TypeElement typeElement = (TypeElement)((DeclaredType)type).asElement();
+ // final String qName = typeElement.getQualifiedName().toString().replace(".", "/");
+ // return "L" + qName + ";";
+ // default:
+ // return null;
+ // }
+ //}
+ }
+
+ //private static class IdentifiersCollector extends TreeScanner<Object, Trees> {
+ // private Set<Name> myIdentifiers = new HashSet<Name>();
+ // private Set<String> myImports = new HashSet<String>();
+ // private Set<String> myStaticImports = new HashSet<String>();
+ //
+ // public Set<String> getIdentifiers() {
+ // final HashSet<String> result = new HashSet<String>();
+ // for (Name name : myIdentifiers) {
+ // result.add(name.toString());
+ // }
+ // return result;
+ // }
+ //
+ // @Override
+ // public Object visitImport(ImportTree node, Trees trees) {
+ // final Tree identifier = node.getQualifiedIdentifier();
+ // final Set<String> container = node.isStatic()? myStaticImports : myImports;
+ // container.add(identifier.toString());
+ // return null;
+ // }
+ //
+ // @Override
+ // public Object visitAnnotation(AnnotationTree node, Trees trees) {
+ // return scan(node.getArguments(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitIdentifier(IdentifierTree node, Trees trees) {
+ // myIdentifiers.add(node.getName());
+ // return super.visitIdentifier(node, trees);
+ // }
+ //
+ // @Override
+ // public Object visitMemberSelect(MemberSelectTree node, Trees trees) {
+ // myIdentifiers.add(node.getIdentifier());
+ // return scan(node.getExpression(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitClass(ClassTree node, Trees trees) {
+ // return scan(node.getMembers(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitVariable(VariableTree node, Trees trees) {
+ // return scan(node.getInitializer(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitMethod(MethodTree node, Trees trees) {
+ // return scan(node.getBody(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) {
+ // return scan(node.getArguments(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitTypeCast(TypeCastTree node, Trees trees) {
+ // return scan(node.getExpression(), trees);
+ // }
+ //
+ // @Override
+ // public Object visitInstanceOf(InstanceOfTree node, Trees trees) {
+ // return scan(node.getExpression(), trees);
+ // }
+ //}
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java
new file mode 100644
index 000000000000..5175787156b2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.incremental.Utils;
+
+import javax.tools.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/24/11
+ */
+class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> implements StandardJavaFileManager{
+
+ private final Context myContext;
+ private Map<File, Set<File>> myOutputsMap = Collections.emptyMap();
+
+ interface Context {
+ boolean isCanceled();
+
+ StandardJavaFileManager getStandardFileManager();
+
+ void consumeOutputFile(@NotNull OutputFileObject obj);
+
+ void reportMessage(final Diagnostic.Kind kind, String message);
+ }
+
+ public JavacFileManager(Context context) {
+ super(context.getStandardFileManager());
+ myContext = context;
+ }
+
+ public void setOutputDirectories(final Map<File, Set<File>> outputDirToSrcRoots) throws IOException{
+ for (File outputDir : outputDirToSrcRoots.keySet()) {
+ // this will validate output dirs
+ setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(outputDir));
+ }
+ myOutputsMap = outputDirToSrcRoots;
+ }
+
+ public void setLocation(Location location, Iterable<? extends File> path) throws IOException{
+ getStdManager().setLocation(location, path);
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
+ return getStdManager().getJavaFileObjectsFromFiles(files);
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
+ return getStdManager().getJavaFileObjects(files);
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
+ return getStdManager().getJavaFileObjectsFromStrings(names);
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
+ return getStdManager().getJavaFileObjects(names);
+ }
+
+ public Iterable<? extends File> getLocation(Location location) {
+ return getStdManager().getLocation(location);
+ }
+
+ public boolean isSameFile(FileObject a, FileObject b) {
+ if (a instanceof OutputFileObject || b instanceof OutputFileObject) {
+ return a.equals(b);
+ }
+ return super.isSameFile(a, b);
+ }
+
+ @Override
+ public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
+ checkCanceled();
+ final FileObject fo = super.getFileForInput(location, packageName, relativeName);
+ if (fo == null) {
+ // workaround javac bug (missing null-check): throwing exception here instead of returning null
+ throw new FileNotFoundException("Resource does not exist : " + location + '/' + packageName + '/' + relativeName);
+ }
+ return fo;
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
+ checkCanceled();
+ final JavaFileObject fo = super.getJavaFileForInput(location, className, kind);
+ if (fo == null) {
+ // workaround javac bug (missing null-check): throwing exception here instead of returning null
+ throw new FileNotFoundException("Java resource does not exist : " + location + '/' + kind + '/' + className);
+ }
+ return fo;
+ }
+
+ public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
+ if (kind != JavaFileObject.Kind.SOURCE && kind != JavaFileObject.Kind.CLASS) {
+ throw new IllegalArgumentException("Invalid kind " + kind);
+ }
+ return getFileForOutput(location, kind, externalizeFileName(className, kind), className, sibling);
+ }
+
+ public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
+ final StringBuilder name = new StringBuilder();
+ if (packageName.isEmpty()) {
+ name.append(relativeName);
+ }
+ else {
+ name.append(externalizeFileName(packageName)).append(File.separatorChar).append(relativeName);
+ }
+ final String fileName = name.toString();
+ return getFileForOutput(location, getKind(fileName), fileName, null, sibling);
+ }
+
+ private OutputFileObject getFileForOutput(Location location, JavaFileObject.Kind kind, String fileName, @Nullable String className, FileObject sibling) throws IOException {
+ checkCanceled();
+
+ JavaFileObject src = null;
+ if (sibling instanceof JavaFileObject) {
+ final JavaFileObject javaFileObject = (JavaFileObject)sibling;
+ if (javaFileObject.getKind() == JavaFileObject.Kind.SOURCE) {
+ src = javaFileObject;
+ }
+ }
+
+ File dir = getSingleOutputDirectory(location, src);
+
+ if (location == StandardLocation.CLASS_OUTPUT) {
+ if (dir == null) {
+ throw new IOException("Output directory is not specified");
+ }
+ }
+ else if (location == StandardLocation.SOURCE_OUTPUT) {
+ if (dir == null) {
+ dir = getSingleOutputDirectory(StandardLocation.CLASS_OUTPUT, src);
+ if (dir == null) {
+ throw new IOException("Neither class output directory nor source output are specified");
+ }
+ }
+ }
+ final File file = (dir == null? new File(fileName).getAbsoluteFile() : new File(dir, fileName));
+ return new OutputFileObject(myContext, dir, fileName, file, kind, className, src != null? src.toUri() : null);
+ }
+
+ private File getSingleOutputDirectory(final Location loc, final JavaFileObject sourceFile) {
+ if (loc == StandardLocation.CLASS_OUTPUT) {
+ if (myOutputsMap.size() > 1 && sourceFile != null) {
+ // multiple outputs case
+ final File outputDir = findOutputDir(Utils.convertToFile(sourceFile.toUri()));
+ if (outputDir != null) {
+ return outputDir;
+ }
+ }
+ }
+
+ final Iterable<? extends File> location = getStdManager().getLocation(loc);
+ if (location != null) {
+ final Iterator<? extends File> it = location.iterator();
+ if (it.hasNext()) {
+ return it.next();
+ }
+ }
+ return null;
+ }
+
+ private File findOutputDir(File src) {
+ File file = FileUtilRt.getParentFile(src);
+ while (file != null) {
+ for (Map.Entry<File, Set<File>> entry : myOutputsMap.entrySet()) {
+ if (entry.getValue().contains(file)) {
+ return entry.getKey();
+ }
+ }
+ file = FileUtilRt.getParentFile(file);
+ }
+ return null;
+ }
+
+ @NotNull
+ private StandardJavaFileManager getStdManager() {
+ return fileManager;
+ }
+
+ public Iterable<? extends JavaFileObject> toJavaFileObjects(Iterable<? extends File> files) {
+ return getStdManager().getJavaFileObjectsFromFiles(files);
+ }
+
+ @Override
+ public void close() {
+ try {
+ super.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ finally {
+ myOutputsMap = Collections.emptyMap();
+ }
+ }
+
+ private static JavaFileObject.Kind getKind(String name) {
+ if (name.endsWith(JavaFileObject.Kind.CLASS.extension)){
+ return JavaFileObject.Kind.CLASS;
+ }
+ if (name.endsWith(JavaFileObject.Kind.SOURCE.extension)) {
+ return JavaFileObject.Kind.SOURCE;
+ }
+ if (name.endsWith(JavaFileObject.Kind.HTML.extension)) {
+ return JavaFileObject.Kind.HTML;
+ }
+ return JavaFileObject.Kind.OTHER;
+ }
+
+ private static String externalizeFileName(CharSequence cs, JavaFileObject.Kind kind) {
+ return externalizeFileName(cs) + kind.extension;
+ }
+
+ private static String externalizeFileName(CharSequence name) {
+ return name.toString().replace('.', File.separatorChar);
+ }
+
+ private int myChecksCounter = 0;
+
+ private void checkCanceled() {
+ final int counter = (myChecksCounter + 1) % 10;
+ myChecksCounter = counter;
+ if (counter == 0 && myContext.isCanceled()) {
+ throw new CompilationCanceledException();
+ }
+ }
+
+ public Context getContext() {
+ return myContext;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
new file mode 100644
index 000000000000..f985b2f81699
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.intellij.openapi.util.SystemInfo;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.cmdline.ClasspathBootstrap;
+import org.jetbrains.jps.incremental.LineOutputWriter;
+
+import javax.tools.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/21/12
+ */
+public class JavacMain {
+ private static final boolean IS_VM_6_VERSION = System.getProperty("java.version", "1.6").contains("1.6");
+ //private static final boolean ECLIPSE_COMPILER_SINGLE_THREADED_MODE = Boolean.parseBoolean(System.getProperty("jdt.compiler.useSingleThread", "false"));
+ private static final Set<String> FILTERED_OPTIONS = new HashSet<String>(Arrays.<String>asList(
+ "-d", "-classpath", "-cp", "-bootclasspath"
+ ));
+ private static final Set<String> FILTERED_SINGLE_OPTIONS = new HashSet<String>(Arrays.<String>asList(
+ /*javac options*/ "-verbose", "-proc:only", "-implicit:class", "-implicit:none",
+ /*eclipse options*/"-noExit"
+ ));
+
+ public static boolean compile(Collection<String> options,
+ final Collection<File> sources,
+ Collection<File> classpath,
+ Collection<File> platformClasspath,
+ Collection<File> sourcePath,
+ Map<File, Set<File>> outputDirToRoots,
+ final DiagnosticOutputConsumer outConsumer,
+ final OutputFileConsumer outputSink,
+ CanceledStatus canceledStatus, boolean useEclipseCompiler) {
+ JavaCompiler compiler = null;
+ if (useEclipseCompiler) {
+ for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) {
+ compiler = javaCompiler;
+ break;
+ }
+ if (compiler == null) {
+ outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath"));
+ return false;
+ }
+ }
+
+ final boolean nowUsingJavac;
+ if (compiler == null) {
+ compiler = ToolProvider.getSystemJavaCompiler();
+ if (compiler == null) {
+ outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "System Java Compiler was not found in classpath"));
+ return false;
+ }
+ nowUsingJavac = true;
+ }
+ else {
+ nowUsingJavac = false;
+ }
+
+ for (File outputDir : outputDirToRoots.keySet()) {
+ outputDir.mkdirs();
+ }
+ final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, outConsumer, outputSink, canceledStatus, nowUsingJavac));
+
+ fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
+ fileManager.handleOption("-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff
+
+ try {
+ fileManager.setOutputDirectories(outputDirToRoots);
+ }
+ catch (IOException e) {
+ fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ return false;
+ }
+
+ if (!classpath.isEmpty()) {
+ try {
+ fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
+ if (!nowUsingJavac && !isOptionSet(options, "-processorpath")) {
+ // for non-javac file manager ensure annotation processor path defaults to classpath
+ fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
+ }
+ }
+ catch (IOException e) {
+ fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ return false;
+ }
+ }
+ if (!platformClasspath.isEmpty()) {
+ try {
+ fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, platformClasspath);
+ }
+ catch (IOException e) {
+ fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ return false;
+ }
+ }
+ try {
+ // ensure the source path is set;
+ // otherwise, if not set, javac attempts to search both classes and sources in classpath;
+ // so if some classpath jars contain sources, it will attempt to compile them
+ fileManager.setLocation(StandardLocation.SOURCE_PATH, sourcePath);
+ }
+ catch (IOException e) {
+ fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ return false;
+ }
+
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ final LineOutputWriter out = new LineOutputWriter() {
+ protected void lineAvailable(String line) {
+ if (nowUsingJavac) {
+ outConsumer.outputLineAvailable(line);
+ }
+ else {
+ // todo: filter too verbose eclipse output?
+ }
+ }
+ };
+
+ try {
+ final Collection<String> _options = prepareOptions(options, nowUsingJavac);
+ final JavaCompiler.CompilationTask task = compiler.getTask(
+ out, fileManager, outConsumer, _options, null, fileManager.toJavaFileObjects(sources)
+ );
+
+ //if (!IS_VM_6_VERSION) { //todo!
+ // // Do not add the processor for JDK 1.6 because of the bugs in javac
+ // // The processor's presence may lead to NPE and resolve bugs in compiler
+ // final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, !annotationProcessingEnabled);
+ // task.setProcessors(Collections.singleton(analyzer));
+ //}
+ return task.call();
+ }
+ catch(IllegalArgumentException e) {
+ outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage()));
+ }
+ catch (CompilationCanceledException ignored) {
+ outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
+ }
+ finally {
+ fileManager.close();
+ }
+ return false;
+ }
+
+ private static boolean isAnnotationProcessingEnabled(final Collection<String> options) {
+ for (String option : options) {
+ if ("-proc:none".equals(option)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isOptionSet(final Collection<String> options, String option) {
+ for (String opt : options) {
+ if (option.equals(opt)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Collection<String> prepareOptions(final Collection<String> options, boolean usingJavac) {
+ final List<String> result = new ArrayList<String>();
+ if (usingJavac) {
+ result.add("-implicit:class"); // the option supported by javac only
+ }
+ else { // is Eclipse
+ result.add("-noExit");
+ }
+ boolean skip = false;
+ for (String option : options) {
+ if (FILTERED_OPTIONS.contains(option)) {
+ skip = true;
+ continue;
+ }
+ if (!skip) {
+ if (!FILTERED_SINGLE_OPTIONS.contains(option)) {
+ result.add(option);
+ }
+ }
+ skip = false;
+ }
+ return result;
+ }
+
+ private static class ContextImpl implements JavacFileManager.Context {
+ private final StandardJavaFileManager myStdManager;
+ private final DiagnosticOutputConsumer myOutConsumer;
+ private final OutputFileConsumer myOutputFileSink;
+ private final CanceledStatus myCanceledStatus;
+
+ public ContextImpl(@NotNull JavaCompiler compiler,
+ @NotNull DiagnosticOutputConsumer outConsumer,
+ @NotNull OutputFileConsumer sink,
+ CanceledStatus canceledStatus, boolean canUseOptimizedmanager) {
+ myOutConsumer = outConsumer;
+ myOutputFileSink = sink;
+ myCanceledStatus = canceledStatus;
+ StandardJavaFileManager stdManager = null;
+ if (canUseOptimizedmanager) {
+ final Class<StandardJavaFileManager> optimizedManagerClass = ClasspathBootstrap.getOptimizedFileManagerClass();
+ if (optimizedManagerClass != null) {
+ try {
+ stdManager = optimizedManagerClass.newInstance();
+ }
+ catch (Throwable e) {
+ if (SystemInfo.isWindows) {
+ System.err.println("Failed to load JPS optimized file manager for javac: " + e.getMessage());
+ }
+ }
+ }
+ }
+ if (stdManager != null) {
+ myStdManager = stdManager;
+ }
+ else {
+ myStdManager = compiler.getStandardFileManager(outConsumer, Locale.US, null);
+ }
+ }
+
+ public boolean isCanceled() {
+ return myCanceledStatus.isCanceled();
+ }
+
+ public StandardJavaFileManager getStandardFileManager() {
+ return myStdManager;
+ }
+
+ public void reportMessage(final Diagnostic.Kind kind, String message) {
+ myOutConsumer.report(new PlainMessageDiagnostic(kind, message));
+ }
+
+ public void consumeOutputFile(@NotNull final OutputFileObject cls) {
+ myOutputFileSink.save(cls);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java
new file mode 100644
index 000000000000..23d0756b8274
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.google.protobuf.ByteString;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.incremental.BinaryContent;
+
+import javax.tools.*;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URI;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/23/12
+ */
+public class JavacProtoUtil {
+
+ public static JavacRemoteProto.Message.Request createCancelRequest() {
+ return JavacRemoteProto.Message.Request.newBuilder().setRequestType(JavacRemoteProto.Message.Request.Type.CANCEL).build();
+ }
+
+ public static JavacRemoteProto.Message.Request createShutdownRequest() {
+ return JavacRemoteProto.Message.Request.newBuilder().setRequestType(JavacRemoteProto.Message.Request.Type.SHUTDOWN).build();
+ }
+
+ public static JavacRemoteProto.Message.Request createCompilationRequest(List<String> options, Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, Map<File, Set<File>> outs) {
+ final JavacRemoteProto.Message.Request.Builder builder = JavacRemoteProto.Message.Request.newBuilder();
+ builder.setRequestType(JavacRemoteProto.Message.Request.Type.COMPILE);
+ builder.addAllOption(options);
+ for (File file : files) {
+ builder.addFile(FileUtil.toSystemIndependentName(file.getPath()));
+ }
+ for (File file : classpath) {
+ builder.addClasspath(FileUtil.toSystemIndependentName(file.getPath()));
+ }
+ for (File file : platformCp) {
+ builder.addPlatformClasspath(FileUtil.toSystemIndependentName(file.getPath()));
+ }
+ for (File file : sourcePath) {
+ builder.addSourcepath(FileUtil.toSystemIndependentName(file.getPath()));
+ }
+ for (Map.Entry<File, Set<File>> entry : outs.entrySet()) {
+ final JavacRemoteProto.Message.Request.OutputGroup.Builder groupBuilder = JavacRemoteProto.Message.Request.OutputGroup.newBuilder();
+ groupBuilder.setOutputRoot(FileUtil.toSystemIndependentName(entry.getKey().getPath()));
+ for (File srcRoot : entry.getValue()) {
+ groupBuilder.addSourceRoot(FileUtil.toSystemIndependentName(srcRoot.getPath()));
+ }
+ builder.addOutput(groupBuilder.build());
+ }
+ return builder.build();
+ }
+
+
+ public static JavacRemoteProto.Message.Response createOutputObjectResponse(OutputFileObject fileObject) {
+ final JavacRemoteProto.Message.Response.OutputObject.Builder msgBuilder = JavacRemoteProto.Message.Response.OutputObject.newBuilder();
+
+ msgBuilder.setKind(convertKind(fileObject.getKind()));
+ msgBuilder.setFilePath(FileUtil.toSystemIndependentName(fileObject.getFile().getPath()));
+ final BinaryContent content = fileObject.getContent();
+ if (content != null) {
+ msgBuilder.setContent(ByteString.copyFrom(content.getBuffer(), content.getOffset(), content.getLength()));
+ }
+ final String className = fileObject.getClassName();
+ if (className != null) {
+ msgBuilder.setClassName(className);
+ }
+ final File outputRoot = fileObject.getOutputRoot();
+ if (outputRoot != null) {
+ msgBuilder.setOutputRoot(FileUtil.toSystemIndependentName(outputRoot.getPath()));
+ }
+ final String relativePath = fileObject.getRelativePath();
+ if (relativePath != null) {
+ msgBuilder.setRelativePath(relativePath);
+ }
+ final URI srcUri = fileObject.getSourceUri();
+ if (srcUri != null) {
+ msgBuilder.setSourceUri(srcUri.toString());
+ }
+
+ final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder();
+ builder.setResponseType(JavacRemoteProto.Message.Response.Type.OUTPUT_OBJECT).setOutputObject(msgBuilder.build());
+
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message.Response createClassDataResponse(String className, Collection<String> imports, Collection<String> staticImports) {
+ final JavacRemoteProto.Message.Response.ClassData.Builder msgBuilder = JavacRemoteProto.Message.Response.ClassData.newBuilder();
+ msgBuilder.setClassName(className);
+ if (!imports.isEmpty()) {
+ msgBuilder.addAllImportStatement(imports);
+ }
+ if (!staticImports.isEmpty()) {
+ msgBuilder.addAllStaticImport(imports);
+ }
+ final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder();
+ builder.setResponseType(JavacRemoteProto.Message.Response.Type.CLASS_DATA).setClassData(msgBuilder.build());
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message.Response createStdOutputResponse(String text) {
+ final JavacRemoteProto.Message.Response.CompileMessage.Builder msgBuilder = JavacRemoteProto.Message.Response.CompileMessage.newBuilder();
+ msgBuilder.setKind(JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT);
+ msgBuilder.setText(text);
+ final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder();
+ builder.setResponseType(JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE).setCompileMessage(msgBuilder.build());
+
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message.Response createBuildMessageResponse(Diagnostic<? extends JavaFileObject> diagnostic) {
+ final JavacRemoteProto.Message.Response.CompileMessage.Builder msgBuilder = JavacRemoteProto.Message.Response.CompileMessage.newBuilder();
+
+ msgBuilder.setKind(convertKind(diagnostic.getKind()));
+ msgBuilder.setText(diagnostic.getMessage(Locale.US));
+
+ final JavaFileObject source = diagnostic.getSource();
+ URI srcUri = null;
+ try {
+ srcUri = source != null? source.toUri() : null;
+ }
+ catch (Exception ignored) {
+ }
+ if (srcUri != null) {
+ msgBuilder.setSourceUri(srcUri.toString());
+ }
+ msgBuilder.setLine(diagnostic.getLineNumber());
+ msgBuilder.setColumn(diagnostic.getColumnNumber());
+ msgBuilder.setProblemBeginOffset(diagnostic.getStartPosition());
+ msgBuilder.setProblemEndOffset(diagnostic.getEndPosition());
+ msgBuilder.setProblemLocationOffset(diagnostic.getPosition());
+
+ final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder();
+ builder.setResponseType(JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE).setCompileMessage(msgBuilder.build());
+
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message.Response createRequestAckResponse() {
+ return JavacRemoteProto.Message.Response.newBuilder().setResponseType(JavacRemoteProto.Message.Response.Type.REQUEST_ACK).build();
+ }
+
+ public static JavacRemoteProto.Message.Response createBuildCompletedResponse(boolean code) {
+ final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder();
+ builder.setResponseType(JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED).setCompletionStatus(code);
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message.Failure createFailure(String description, @Nullable Throwable ex) {
+ final JavacRemoteProto.Message.Failure.Builder builder = JavacRemoteProto.Message.Failure.newBuilder();
+ builder.setDescription(description);
+ if (ex != null) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ex.printStackTrace(new PrintStream(baos));
+ builder.setStacktrace(new String(baos.toByteArray()));
+ }
+ return builder.build();
+ }
+
+ public static JavacRemoteProto.Message toMessage(UUID requestId, JavacRemoteProto.Message.Request request) {
+ return JavacRemoteProto.Message.newBuilder().setMessageType(JavacRemoteProto.Message.Type.REQUEST).setSessionId(toProtoUUID(requestId)).setRequest(request).build();
+ }
+
+ public static JavacRemoteProto.Message toMessage(UUID requestId, JavacRemoteProto.Message.Response response) {
+ return JavacRemoteProto.Message.newBuilder().setMessageType(JavacRemoteProto.Message.Type.RESPONSE).setSessionId(toProtoUUID(requestId)).setResponse(response).build();
+ }
+
+ public static JavacRemoteProto.Message toMessage(UUID requestId, JavacRemoteProto.Message.Failure failure) {
+ return JavacRemoteProto.Message.newBuilder().setMessageType(JavacRemoteProto.Message.Type.FAILURE).setSessionId(toProtoUUID(requestId)).setFailure(failure).build();
+ }
+
+ public static JavacRemoteProto.Message.UUID toProtoUUID(UUID requestId) {
+ return JavacRemoteProto.Message.UUID.newBuilder().setMostSigBits(requestId.getMostSignificantBits()).setLeastSigBits(requestId.getLeastSignificantBits()).build();
+ }
+ public static UUID fromProtoUUID(JavacRemoteProto.Message.UUID requestId) {
+ return new UUID(requestId.getMostSigBits(), requestId.getLeastSigBits());
+ }
+
+ private static JavacRemoteProto.Message.Response.OutputObject.Kind convertKind(JavaFileObject.Kind kind) {
+ switch (kind) {
+ case CLASS:
+ return JavacRemoteProto.Message.Response.OutputObject.Kind.CLASS;
+ case SOURCE:
+ return JavacRemoteProto.Message.Response.OutputObject.Kind.SOURCE;
+ case HTML:
+ return JavacRemoteProto.Message.Response.OutputObject.Kind.HTML;
+ default:
+ return JavacRemoteProto.Message.Response.OutputObject.Kind.OTHER;
+ }
+ }
+ private static JavacRemoteProto.Message.Response.CompileMessage.Kind convertKind(Diagnostic.Kind kind) {
+ switch (kind) {
+ case ERROR: return JavacRemoteProto.Message.Response.CompileMessage.Kind.ERROR;
+ case MANDATORY_WARNING: return JavacRemoteProto.Message.Response.CompileMessage.Kind.MANDATORY_WARNING;
+ case WARNING: return JavacRemoteProto.Message.Response.CompileMessage.Kind.WARNING;
+ case NOTE: return JavacRemoteProto.Message.Response.CompileMessage.Kind.NOTE;
+ default:
+ return JavacRemoteProto.Message.Response.CompileMessage.Kind.OTHER;
+ }
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java
new file mode 100644
index 000000000000..f1886d2d42e9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java
@@ -0,0 +1,6126 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: javac_remote_proto.proto
+
+package org.jetbrains.jps.javac;
+
+public final class JavacRemoteProto {
+ private JavacRemoteProto() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+ public interface MessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.javac.Message.UUID session_id = 1;
+ boolean hasSessionId();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID getSessionId();
+
+ // required .org.jetbrains.javac.Message.Type message_type = 2;
+ boolean hasMessageType();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Type getMessageType();
+
+ // optional .org.jetbrains.javac.Message.Request request = 3;
+ boolean hasRequest();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request getRequest();
+
+ // optional .org.jetbrains.javac.Message.Response response = 4;
+ boolean hasResponse();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response getResponse();
+
+ // optional .org.jetbrains.javac.Message.Failure failure = 5;
+ boolean hasFailure();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure getFailure();
+ }
+ public static final class Message extends
+ com.google.protobuf.GeneratedMessageLite
+ implements MessageOrBuilder {
+ // Use Message.newBuilder() to construct.
+ private Message(Builder builder) {
+ super(builder);
+ }
+ private Message(boolean noInit) {}
+
+ private static final Message defaultInstance;
+ public static Message getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Message getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ REQUEST(0, 1),
+ RESPONSE(1, 2),
+ FAILURE(2, 3),
+ ;
+
+ public static final int REQUEST_VALUE = 1;
+ public static final int RESPONSE_VALUE = 2;
+ public static final int FAILURE_VALUE = 3;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return REQUEST;
+ case 2: return RESPONSE;
+ case 3: return FAILURE;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.javac.Message.Type)
+ }
+
+ public interface UUIDOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required sint64 most_sig_bits = 1;
+ boolean hasMostSigBits();
+ long getMostSigBits();
+
+ // required sint64 least_sig_bits = 2;
+ boolean hasLeastSigBits();
+ long getLeastSigBits();
+ }
+ public static final class UUID extends
+ com.google.protobuf.GeneratedMessageLite
+ implements UUIDOrBuilder {
+ // Use UUID.newBuilder() to construct.
+ private UUID(Builder builder) {
+ super(builder);
+ }
+ private UUID(boolean noInit) {}
+
+ private static final UUID defaultInstance;
+ public static UUID getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public UUID getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required sint64 most_sig_bits = 1;
+ public static final int MOST_SIG_BITS_FIELD_NUMBER = 1;
+ private long mostSigBits_;
+ public boolean hasMostSigBits() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getMostSigBits() {
+ return mostSigBits_;
+ }
+
+ // required sint64 least_sig_bits = 2;
+ public static final int LEAST_SIG_BITS_FIELD_NUMBER = 2;
+ private long leastSigBits_;
+ public boolean hasLeastSigBits() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public long getLeastSigBits() {
+ return leastSigBits_;
+ }
+
+ private void initFields() {
+ mostSigBits_ = 0L;
+ leastSigBits_ = 0L;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasMostSigBits()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasLeastSigBits()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeSInt64(1, mostSigBits_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeSInt64(2, leastSigBits_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeSInt64Size(1, mostSigBits_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeSInt64Size(2, leastSigBits_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.UUIDOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ mostSigBits_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ leastSigBits_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.mostSigBits_ = mostSigBits_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.leastSigBits_ = leastSigBits_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance()) return this;
+ if (other.hasMostSigBits()) {
+ setMostSigBits(other.getMostSigBits());
+ }
+ if (other.hasLeastSigBits()) {
+ setLeastSigBits(other.getLeastSigBits());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasMostSigBits()) {
+
+ return false;
+ }
+ if (!hasLeastSigBits()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ mostSigBits_ = input.readSInt64();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ leastSigBits_ = input.readSInt64();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required sint64 most_sig_bits = 1;
+ private long mostSigBits_ ;
+ public boolean hasMostSigBits() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public long getMostSigBits() {
+ return mostSigBits_;
+ }
+ public Builder setMostSigBits(long value) {
+ bitField0_ |= 0x00000001;
+ mostSigBits_ = value;
+
+ return this;
+ }
+ public Builder clearMostSigBits() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ mostSigBits_ = 0L;
+
+ return this;
+ }
+
+ // required sint64 least_sig_bits = 2;
+ private long leastSigBits_ ;
+ public boolean hasLeastSigBits() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public long getLeastSigBits() {
+ return leastSigBits_;
+ }
+ public Builder setLeastSigBits(long value) {
+ bitField0_ |= 0x00000002;
+ leastSigBits_ = value;
+
+ return this;
+ }
+ public Builder clearLeastSigBits() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ leastSigBits_ = 0L;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.UUID)
+ }
+
+ static {
+ defaultInstance = new UUID(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.UUID)
+ }
+
+ public interface FailureOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // optional int32 error_code = 1;
+ boolean hasErrorCode();
+ int getErrorCode();
+
+ // optional string description = 2;
+ boolean hasDescription();
+ String getDescription();
+
+ // optional string stacktrace = 3;
+ boolean hasStacktrace();
+ String getStacktrace();
+ }
+ public static final class Failure extends
+ com.google.protobuf.GeneratedMessageLite
+ implements FailureOrBuilder {
+ // Use Failure.newBuilder() to construct.
+ private Failure(Builder builder) {
+ super(builder);
+ }
+ private Failure(boolean noInit) {}
+
+ private static final Failure defaultInstance;
+ public static Failure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Failure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // optional int32 error_code = 1;
+ public static final int ERROR_CODE_FIELD_NUMBER = 1;
+ private int errorCode_;
+ public boolean hasErrorCode() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public int getErrorCode() {
+ return errorCode_;
+ }
+
+ // optional string description = 2;
+ public static final int DESCRIPTION_FIELD_NUMBER = 2;
+ private java.lang.Object description_;
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ description_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getDescriptionBytes() {
+ java.lang.Object ref = description_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ description_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string stacktrace = 3;
+ public static final int STACKTRACE_FIELD_NUMBER = 3;
+ private java.lang.Object stacktrace_;
+ public boolean hasStacktrace() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getStacktrace() {
+ java.lang.Object ref = stacktrace_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ stacktrace_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getStacktraceBytes() {
+ java.lang.Object ref = stacktrace_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ stacktrace_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private void initFields() {
+ errorCode_ = 0;
+ description_ = "";
+ stacktrace_ = "";
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(1, errorCode_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getStacktraceBytes());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, errorCode_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getDescriptionBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getStacktraceBytes());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.FailureOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ errorCode_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ description_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ stacktrace_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.errorCode_ = errorCode_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.description_ = description_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.stacktrace_ = stacktrace_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance()) return this;
+ if (other.hasErrorCode()) {
+ setErrorCode(other.getErrorCode());
+ }
+ if (other.hasDescription()) {
+ setDescription(other.getDescription());
+ }
+ if (other.hasStacktrace()) {
+ setStacktrace(other.getStacktrace());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ errorCode_ = input.readInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ description_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ stacktrace_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // optional int32 error_code = 1;
+ private int errorCode_ ;
+ public boolean hasErrorCode() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public int getErrorCode() {
+ return errorCode_;
+ }
+ public Builder setErrorCode(int value) {
+ bitField0_ |= 0x00000001;
+ errorCode_ = value;
+
+ return this;
+ }
+ public Builder clearErrorCode() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ errorCode_ = 0;
+
+ return this;
+ }
+
+ // optional string description = 2;
+ private java.lang.Object description_ = "";
+ public boolean hasDescription() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getDescription() {
+ java.lang.Object ref = description_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ description_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setDescription(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ return this;
+ }
+ public Builder clearDescription() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ description_ = getDefaultInstance().getDescription();
+
+ return this;
+ }
+ void setDescription(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ description_ = value;
+
+ }
+
+ // optional string stacktrace = 3;
+ private java.lang.Object stacktrace_ = "";
+ public boolean hasStacktrace() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getStacktrace() {
+ java.lang.Object ref = stacktrace_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ stacktrace_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setStacktrace(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ stacktrace_ = value;
+
+ return this;
+ }
+ public Builder clearStacktrace() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ stacktrace_ = getDefaultInstance().getStacktrace();
+
+ return this;
+ }
+ void setStacktrace(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ stacktrace_ = value;
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Failure)
+ }
+
+ static {
+ defaultInstance = new Failure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Failure)
+ }
+
+ public interface RequestOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.javac.Message.Request.Type request_type = 1;
+ boolean hasRequestType();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type getRequestType();
+
+ // repeated string option = 2;
+ java.util.List<String> getOptionList();
+ int getOptionCount();
+ String getOption(int index);
+
+ // repeated string file = 3;
+ java.util.List<String> getFileList();
+ int getFileCount();
+ String getFile(int index);
+
+ // repeated string platform_classpath = 4;
+ java.util.List<String> getPlatformClasspathList();
+ int getPlatformClasspathCount();
+ String getPlatformClasspath(int index);
+
+ // repeated string classpath = 5;
+ java.util.List<String> getClasspathList();
+ int getClasspathCount();
+ String getClasspath(int index);
+
+ // repeated string sourcepath = 6;
+ java.util.List<String> getSourcepathList();
+ int getSourcepathCount();
+ String getSourcepath(int index);
+
+ // repeated .org.jetbrains.javac.Message.Request.OutputGroup output = 7;
+ java.util.List<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup>
+ getOutputList();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup getOutput(int index);
+ int getOutputCount();
+ }
+ public static final class Request extends
+ com.google.protobuf.GeneratedMessageLite
+ implements RequestOrBuilder {
+ // Use Request.newBuilder() to construct.
+ private Request(Builder builder) {
+ super(builder);
+ }
+ private Request(boolean noInit) {}
+
+ private static final Request defaultInstance;
+ public static Request getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Request getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ COMPILE(0, 1),
+ CANCEL(1, 2),
+ SHUTDOWN(2, 3),
+ ;
+
+ public static final int COMPILE_VALUE = 1;
+ public static final int CANCEL_VALUE = 2;
+ public static final int SHUTDOWN_VALUE = 3;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return COMPILE;
+ case 2: return CANCEL;
+ case 3: return SHUTDOWN;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.javac.Message.Request.Type)
+ }
+
+ public interface OutputGroupOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string output_root = 1;
+ boolean hasOutputRoot();
+ String getOutputRoot();
+
+ // repeated string source_root = 2;
+ java.util.List<String> getSourceRootList();
+ int getSourceRootCount();
+ String getSourceRoot(int index);
+ }
+ public static final class OutputGroup extends
+ com.google.protobuf.GeneratedMessageLite
+ implements OutputGroupOrBuilder {
+ // Use OutputGroup.newBuilder() to construct.
+ private OutputGroup(Builder builder) {
+ super(builder);
+ }
+ private OutputGroup(boolean noInit) {}
+
+ private static final OutputGroup defaultInstance;
+ public static OutputGroup getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public OutputGroup getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string output_root = 1;
+ public static final int OUTPUT_ROOT_FIELD_NUMBER = 1;
+ private java.lang.Object outputRoot_;
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ outputRoot_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getOutputRootBytes() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ outputRoot_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // repeated string source_root = 2;
+ public static final int SOURCE_ROOT_FIELD_NUMBER = 2;
+ private com.google.protobuf.LazyStringList sourceRoot_;
+ public java.util.List<String>
+ getSourceRootList() {
+ return sourceRoot_;
+ }
+ public int getSourceRootCount() {
+ return sourceRoot_.size();
+ }
+ public String getSourceRoot(int index) {
+ return sourceRoot_.get(index);
+ }
+
+ private void initFields() {
+ outputRoot_ = "";
+ sourceRoot_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasOutputRoot()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getOutputRootBytes());
+ }
+ for (int i = 0; i < sourceRoot_.size(); i++) {
+ output.writeBytes(2, sourceRoot_.getByteString(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getOutputRootBytes());
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < sourceRoot_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(sourceRoot_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getSourceRootList().size();
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroupOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ outputRoot_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ sourceRoot_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.outputRoot_ = outputRoot_;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ sourceRoot_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ sourceRoot_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.sourceRoot_ = sourceRoot_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.getDefaultInstance()) return this;
+ if (other.hasOutputRoot()) {
+ setOutputRoot(other.getOutputRoot());
+ }
+ if (!other.sourceRoot_.isEmpty()) {
+ if (sourceRoot_.isEmpty()) {
+ sourceRoot_ = other.sourceRoot_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensureSourceRootIsMutable();
+ sourceRoot_.addAll(other.sourceRoot_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasOutputRoot()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ outputRoot_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ ensureSourceRootIsMutable();
+ sourceRoot_.add(input.readBytes());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string output_root = 1;
+ private java.lang.Object outputRoot_ = "";
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ outputRoot_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setOutputRoot(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ outputRoot_ = value;
+
+ return this;
+ }
+ public Builder clearOutputRoot() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ outputRoot_ = getDefaultInstance().getOutputRoot();
+
+ return this;
+ }
+ void setOutputRoot(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ outputRoot_ = value;
+
+ }
+
+ // repeated string source_root = 2;
+ private com.google.protobuf.LazyStringList sourceRoot_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureSourceRootIsMutable() {
+ if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+ sourceRoot_ = new com.google.protobuf.LazyStringArrayList(sourceRoot_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+ public java.util.List<String>
+ getSourceRootList() {
+ return java.util.Collections.unmodifiableList(sourceRoot_);
+ }
+ public int getSourceRootCount() {
+ return sourceRoot_.size();
+ }
+ public String getSourceRoot(int index) {
+ return sourceRoot_.get(index);
+ }
+ public Builder setSourceRoot(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSourceRootIsMutable();
+ sourceRoot_.set(index, value);
+
+ return this;
+ }
+ public Builder addSourceRoot(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSourceRootIsMutable();
+ sourceRoot_.add(value);
+
+ return this;
+ }
+ public Builder addAllSourceRoot(
+ java.lang.Iterable<String> values) {
+ ensureSourceRootIsMutable();
+ super.addAll(values, sourceRoot_);
+
+ return this;
+ }
+ public Builder clearSourceRoot() {
+ sourceRoot_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+
+ return this;
+ }
+ void addSourceRoot(com.google.protobuf.ByteString value) {
+ ensureSourceRootIsMutable();
+ sourceRoot_.add(value);
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Request.OutputGroup)
+ }
+
+ static {
+ defaultInstance = new OutputGroup(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Request.OutputGroup)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.javac.Message.Request.Type request_type = 1;
+ public static final int REQUEST_TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type requestType_;
+ public boolean hasRequestType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type getRequestType() {
+ return requestType_;
+ }
+
+ // repeated string option = 2;
+ public static final int OPTION_FIELD_NUMBER = 2;
+ private com.google.protobuf.LazyStringList option_;
+ public java.util.List<String>
+ getOptionList() {
+ return option_;
+ }
+ public int getOptionCount() {
+ return option_.size();
+ }
+ public String getOption(int index) {
+ return option_.get(index);
+ }
+
+ // repeated string file = 3;
+ public static final int FILE_FIELD_NUMBER = 3;
+ private com.google.protobuf.LazyStringList file_;
+ public java.util.List<String>
+ getFileList() {
+ return file_;
+ }
+ public int getFileCount() {
+ return file_.size();
+ }
+ public String getFile(int index) {
+ return file_.get(index);
+ }
+
+ // repeated string platform_classpath = 4;
+ public static final int PLATFORM_CLASSPATH_FIELD_NUMBER = 4;
+ private com.google.protobuf.LazyStringList platformClasspath_;
+ public java.util.List<String>
+ getPlatformClasspathList() {
+ return platformClasspath_;
+ }
+ public int getPlatformClasspathCount() {
+ return platformClasspath_.size();
+ }
+ public String getPlatformClasspath(int index) {
+ return platformClasspath_.get(index);
+ }
+
+ // repeated string classpath = 5;
+ public static final int CLASSPATH_FIELD_NUMBER = 5;
+ private com.google.protobuf.LazyStringList classpath_;
+ public java.util.List<String>
+ getClasspathList() {
+ return classpath_;
+ }
+ public int getClasspathCount() {
+ return classpath_.size();
+ }
+ public String getClasspath(int index) {
+ return classpath_.get(index);
+ }
+
+ // repeated string sourcepath = 6;
+ public static final int SOURCEPATH_FIELD_NUMBER = 6;
+ private com.google.protobuf.LazyStringList sourcepath_;
+ public java.util.List<String>
+ getSourcepathList() {
+ return sourcepath_;
+ }
+ public int getSourcepathCount() {
+ return sourcepath_.size();
+ }
+ public String getSourcepath(int index) {
+ return sourcepath_.get(index);
+ }
+
+ // repeated .org.jetbrains.javac.Message.Request.OutputGroup output = 7;
+ public static final int OUTPUT_FIELD_NUMBER = 7;
+ private java.util.List<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup> output_;
+ public java.util.List<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup> getOutputList() {
+ return output_;
+ }
+ public java.util.List<? extends org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroupOrBuilder>
+ getOutputOrBuilderList() {
+ return output_;
+ }
+ public int getOutputCount() {
+ return output_.size();
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup getOutput(int index) {
+ return output_.get(index);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroupOrBuilder getOutputOrBuilder(
+ int index) {
+ return output_.get(index);
+ }
+
+ private void initFields() {
+ requestType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type.COMPILE;
+ option_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ file_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ platformClasspath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ classpath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ sourcepath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ output_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasRequestType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ for (int i = 0; i < getOutputCount(); i++) {
+ if (!getOutput(i).isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, requestType_.getNumber());
+ }
+ for (int i = 0; i < option_.size(); i++) {
+ output.writeBytes(2, option_.getByteString(i));
+ }
+ for (int i = 0; i < file_.size(); i++) {
+ output.writeBytes(3, file_.getByteString(i));
+ }
+ for (int i = 0; i < platformClasspath_.size(); i++) {
+ output.writeBytes(4, platformClasspath_.getByteString(i));
+ }
+ for (int i = 0; i < classpath_.size(); i++) {
+ output.writeBytes(5, classpath_.getByteString(i));
+ }
+ for (int i = 0; i < sourcepath_.size(); i++) {
+ output.writeBytes(6, sourcepath_.getByteString(i));
+ }
+ for (int i = 0; i < output_.size(); i++) {
+ output.writeMessage(7, output_.get(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, requestType_.getNumber());
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < option_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(option_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getOptionList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < file_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(file_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getFileList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < platformClasspath_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(platformClasspath_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getPlatformClasspathList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < classpath_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(classpath_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getClasspathList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < sourcepath_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(sourcepath_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getSourcepathList().size();
+ }
+ for (int i = 0; i < output_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(7, output_.get(i));
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Request parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.RequestOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ requestType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type.COMPILE;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ option_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ file_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ platformClasspath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ classpath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ sourcepath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ output_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000040);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Request(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.requestType_ = requestType_;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ option_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ option_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.option_ = option_;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ file_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ file_);
+ bitField0_ = (bitField0_ & ~0x00000004);
+ }
+ result.file_ = file_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ platformClasspath_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ platformClasspath_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.platformClasspath_ = platformClasspath_;
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ classpath_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ classpath_);
+ bitField0_ = (bitField0_ & ~0x00000010);
+ }
+ result.classpath_ = classpath_;
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ sourcepath_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ sourcepath_);
+ bitField0_ = (bitField0_ & ~0x00000020);
+ }
+ result.sourcepath_ = sourcepath_;
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output_ = java.util.Collections.unmodifiableList(output_);
+ bitField0_ = (bitField0_ & ~0x00000040);
+ }
+ result.output_ = output_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance()) return this;
+ if (other.hasRequestType()) {
+ setRequestType(other.getRequestType());
+ }
+ if (!other.option_.isEmpty()) {
+ if (option_.isEmpty()) {
+ option_ = other.option_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensureOptionIsMutable();
+ option_.addAll(other.option_);
+ }
+
+ }
+ if (!other.file_.isEmpty()) {
+ if (file_.isEmpty()) {
+ file_ = other.file_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureFileIsMutable();
+ file_.addAll(other.file_);
+ }
+
+ }
+ if (!other.platformClasspath_.isEmpty()) {
+ if (platformClasspath_.isEmpty()) {
+ platformClasspath_ = other.platformClasspath_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensurePlatformClasspathIsMutable();
+ platformClasspath_.addAll(other.platformClasspath_);
+ }
+
+ }
+ if (!other.classpath_.isEmpty()) {
+ if (classpath_.isEmpty()) {
+ classpath_ = other.classpath_;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ } else {
+ ensureClasspathIsMutable();
+ classpath_.addAll(other.classpath_);
+ }
+
+ }
+ if (!other.sourcepath_.isEmpty()) {
+ if (sourcepath_.isEmpty()) {
+ sourcepath_ = other.sourcepath_;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ } else {
+ ensureSourcepathIsMutable();
+ sourcepath_.addAll(other.sourcepath_);
+ }
+
+ }
+ if (!other.output_.isEmpty()) {
+ if (output_.isEmpty()) {
+ output_ = other.output_;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ } else {
+ ensureOutputIsMutable();
+ output_.addAll(other.output_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasRequestType()) {
+
+ return false;
+ }
+ for (int i = 0; i < getOutputCount(); i++) {
+ if (!getOutput(i).isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type value = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ requestType_ = value;
+ }
+ break;
+ }
+ case 18: {
+ ensureOptionIsMutable();
+ option_.add(input.readBytes());
+ break;
+ }
+ case 26: {
+ ensureFileIsMutable();
+ file_.add(input.readBytes());
+ break;
+ }
+ case 34: {
+ ensurePlatformClasspathIsMutable();
+ platformClasspath_.add(input.readBytes());
+ break;
+ }
+ case 42: {
+ ensureClasspathIsMutable();
+ classpath_.add(input.readBytes());
+ break;
+ }
+ case 50: {
+ ensureSourcepathIsMutable();
+ sourcepath_.add(input.readBytes());
+ break;
+ }
+ case 58: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addOutput(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.javac.Message.Request.Type request_type = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type requestType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type.COMPILE;
+ public boolean hasRequestType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type getRequestType() {
+ return requestType_;
+ }
+ public Builder setRequestType(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ requestType_ = value;
+
+ return this;
+ }
+ public Builder clearRequestType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ requestType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Type.COMPILE;
+
+ return this;
+ }
+
+ // repeated string option = 2;
+ private com.google.protobuf.LazyStringList option_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureOptionIsMutable() {
+ if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+ option_ = new com.google.protobuf.LazyStringArrayList(option_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+ public java.util.List<String>
+ getOptionList() {
+ return java.util.Collections.unmodifiableList(option_);
+ }
+ public int getOptionCount() {
+ return option_.size();
+ }
+ public String getOption(int index) {
+ return option_.get(index);
+ }
+ public Builder setOption(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureOptionIsMutable();
+ option_.set(index, value);
+
+ return this;
+ }
+ public Builder addOption(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureOptionIsMutable();
+ option_.add(value);
+
+ return this;
+ }
+ public Builder addAllOption(
+ java.lang.Iterable<String> values) {
+ ensureOptionIsMutable();
+ super.addAll(values, option_);
+
+ return this;
+ }
+ public Builder clearOption() {
+ option_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+
+ return this;
+ }
+ void addOption(com.google.protobuf.ByteString value) {
+ ensureOptionIsMutable();
+ option_.add(value);
+
+ }
+
+ // repeated string file = 3;
+ private com.google.protobuf.LazyStringList file_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureFileIsMutable() {
+ if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+ file_ = new com.google.protobuf.LazyStringArrayList(file_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+ public java.util.List<String>
+ getFileList() {
+ return java.util.Collections.unmodifiableList(file_);
+ }
+ public int getFileCount() {
+ return file_.size();
+ }
+ public String getFile(int index) {
+ return file_.get(index);
+ }
+ public Builder setFile(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureFileIsMutable();
+ file_.set(index, value);
+
+ return this;
+ }
+ public Builder addFile(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureFileIsMutable();
+ file_.add(value);
+
+ return this;
+ }
+ public Builder addAllFile(
+ java.lang.Iterable<String> values) {
+ ensureFileIsMutable();
+ super.addAll(values, file_);
+
+ return this;
+ }
+ public Builder clearFile() {
+ file_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+
+ return this;
+ }
+ void addFile(com.google.protobuf.ByteString value) {
+ ensureFileIsMutable();
+ file_.add(value);
+
+ }
+
+ // repeated string platform_classpath = 4;
+ private com.google.protobuf.LazyStringList platformClasspath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensurePlatformClasspathIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ platformClasspath_ = new com.google.protobuf.LazyStringArrayList(platformClasspath_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+ public java.util.List<String>
+ getPlatformClasspathList() {
+ return java.util.Collections.unmodifiableList(platformClasspath_);
+ }
+ public int getPlatformClasspathCount() {
+ return platformClasspath_.size();
+ }
+ public String getPlatformClasspath(int index) {
+ return platformClasspath_.get(index);
+ }
+ public Builder setPlatformClasspath(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePlatformClasspathIsMutable();
+ platformClasspath_.set(index, value);
+
+ return this;
+ }
+ public Builder addPlatformClasspath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePlatformClasspathIsMutable();
+ platformClasspath_.add(value);
+
+ return this;
+ }
+ public Builder addAllPlatformClasspath(
+ java.lang.Iterable<String> values) {
+ ensurePlatformClasspathIsMutable();
+ super.addAll(values, platformClasspath_);
+
+ return this;
+ }
+ public Builder clearPlatformClasspath() {
+ platformClasspath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+
+ return this;
+ }
+ void addPlatformClasspath(com.google.protobuf.ByteString value) {
+ ensurePlatformClasspathIsMutable();
+ platformClasspath_.add(value);
+
+ }
+
+ // repeated string classpath = 5;
+ private com.google.protobuf.LazyStringList classpath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureClasspathIsMutable() {
+ if (!((bitField0_ & 0x00000010) == 0x00000010)) {
+ classpath_ = new com.google.protobuf.LazyStringArrayList(classpath_);
+ bitField0_ |= 0x00000010;
+ }
+ }
+ public java.util.List<String>
+ getClasspathList() {
+ return java.util.Collections.unmodifiableList(classpath_);
+ }
+ public int getClasspathCount() {
+ return classpath_.size();
+ }
+ public String getClasspath(int index) {
+ return classpath_.get(index);
+ }
+ public Builder setClasspath(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureClasspathIsMutable();
+ classpath_.set(index, value);
+
+ return this;
+ }
+ public Builder addClasspath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureClasspathIsMutable();
+ classpath_.add(value);
+
+ return this;
+ }
+ public Builder addAllClasspath(
+ java.lang.Iterable<String> values) {
+ ensureClasspathIsMutable();
+ super.addAll(values, classpath_);
+
+ return this;
+ }
+ public Builder clearClasspath() {
+ classpath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+
+ return this;
+ }
+ void addClasspath(com.google.protobuf.ByteString value) {
+ ensureClasspathIsMutable();
+ classpath_.add(value);
+
+ }
+
+ // repeated string sourcepath = 6;
+ private com.google.protobuf.LazyStringList sourcepath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureSourcepathIsMutable() {
+ if (!((bitField0_ & 0x00000020) == 0x00000020)) {
+ sourcepath_ = new com.google.protobuf.LazyStringArrayList(sourcepath_);
+ bitField0_ |= 0x00000020;
+ }
+ }
+ public java.util.List<String>
+ getSourcepathList() {
+ return java.util.Collections.unmodifiableList(sourcepath_);
+ }
+ public int getSourcepathCount() {
+ return sourcepath_.size();
+ }
+ public String getSourcepath(int index) {
+ return sourcepath_.get(index);
+ }
+ public Builder setSourcepath(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSourcepathIsMutable();
+ sourcepath_.set(index, value);
+
+ return this;
+ }
+ public Builder addSourcepath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSourcepathIsMutable();
+ sourcepath_.add(value);
+
+ return this;
+ }
+ public Builder addAllSourcepath(
+ java.lang.Iterable<String> values) {
+ ensureSourcepathIsMutable();
+ super.addAll(values, sourcepath_);
+
+ return this;
+ }
+ public Builder clearSourcepath() {
+ sourcepath_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000020);
+
+ return this;
+ }
+ void addSourcepath(com.google.protobuf.ByteString value) {
+ ensureSourcepathIsMutable();
+ sourcepath_.add(value);
+
+ }
+
+ // repeated .org.jetbrains.javac.Message.Request.OutputGroup output = 7;
+ private java.util.List<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup> output_ =
+ java.util.Collections.emptyList();
+ private void ensureOutputIsMutable() {
+ if (!((bitField0_ & 0x00000040) == 0x00000040)) {
+ output_ = new java.util.ArrayList<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup>(output_);
+ bitField0_ |= 0x00000040;
+ }
+ }
+
+ public java.util.List<org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup> getOutputList() {
+ return java.util.Collections.unmodifiableList(output_);
+ }
+ public int getOutputCount() {
+ return output_.size();
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup getOutput(int index) {
+ return output_.get(index);
+ }
+ public Builder setOutput(
+ int index, org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureOutputIsMutable();
+ output_.set(index, value);
+
+ return this;
+ }
+ public Builder setOutput(
+ int index, org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.Builder builderForValue) {
+ ensureOutputIsMutable();
+ output_.set(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addOutput(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureOutputIsMutable();
+ output_.add(value);
+
+ return this;
+ }
+ public Builder addOutput(
+ int index, org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureOutputIsMutable();
+ output_.add(index, value);
+
+ return this;
+ }
+ public Builder addOutput(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.Builder builderForValue) {
+ ensureOutputIsMutable();
+ output_.add(builderForValue.build());
+
+ return this;
+ }
+ public Builder addOutput(
+ int index, org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup.Builder builderForValue) {
+ ensureOutputIsMutable();
+ output_.add(index, builderForValue.build());
+
+ return this;
+ }
+ public Builder addAllOutput(
+ java.lang.Iterable<? extends org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.OutputGroup> values) {
+ ensureOutputIsMutable();
+ super.addAll(values, output_);
+
+ return this;
+ }
+ public Builder clearOutput() {
+ output_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000040);
+
+ return this;
+ }
+ public Builder removeOutput(int index) {
+ ensureOutputIsMutable();
+ output_.remove(index);
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Request)
+ }
+
+ static {
+ defaultInstance = new Request(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Request)
+ }
+
+ public interface ResponseOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.javac.Message.Response.Type response_type = 1;
+ boolean hasResponseType();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type getResponseType();
+
+ // optional .org.jetbrains.javac.Message.Response.CompileMessage compile_message = 2;
+ boolean hasCompileMessage();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage getCompileMessage();
+
+ // optional .org.jetbrains.javac.Message.Response.OutputObject output_object = 3;
+ boolean hasOutputObject();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getOutputObject();
+
+ // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4;
+ boolean hasClassData();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData();
+
+ // optional bool completion_status = 5;
+ boolean hasCompletionStatus();
+ boolean getCompletionStatus();
+ }
+ public static final class Response extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ResponseOrBuilder {
+ // Use Response.newBuilder() to construct.
+ private Response(Builder builder) {
+ super(builder);
+ }
+ private Response(boolean noInit) {}
+
+ private static final Response defaultInstance;
+ public static Response getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Response getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Type
+ implements com.google.protobuf.Internal.EnumLite {
+ BUILD_MESSAGE(0, 1),
+ OUTPUT_OBJECT(1, 2),
+ CLASS_DATA(2, 3),
+ BUILD_COMPLETED(3, 4),
+ REQUEST_ACK(4, 5),
+ ;
+
+ public static final int BUILD_MESSAGE_VALUE = 1;
+ public static final int OUTPUT_OBJECT_VALUE = 2;
+ public static final int CLASS_DATA_VALUE = 3;
+ public static final int BUILD_COMPLETED_VALUE = 4;
+ public static final int REQUEST_ACK_VALUE = 5;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 1: return BUILD_MESSAGE;
+ case 2: return OUTPUT_OBJECT;
+ case 3: return CLASS_DATA;
+ case 4: return BUILD_COMPLETED;
+ case 5: return REQUEST_ACK;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Type>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Type>() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Type(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.javac.Message.Response.Type)
+ }
+
+ public interface CompileMessageOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.javac.Message.Response.CompileMessage.Kind kind = 1;
+ boolean hasKind();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind getKind();
+
+ // optional string text = 2;
+ boolean hasText();
+ String getText();
+
+ // optional string source_uri = 3;
+ boolean hasSourceUri();
+ String getSourceUri();
+
+ // optional uint64 problem_begin_offset = 4;
+ boolean hasProblemBeginOffset();
+ long getProblemBeginOffset();
+
+ // optional uint64 problem_end_offset = 5;
+ boolean hasProblemEndOffset();
+ long getProblemEndOffset();
+
+ // optional uint64 problem_location_offset = 6;
+ boolean hasProblemLocationOffset();
+ long getProblemLocationOffset();
+
+ // optional uint64 line = 7;
+ boolean hasLine();
+ long getLine();
+
+ // optional uint64 column = 8;
+ boolean hasColumn();
+ long getColumn();
+ }
+ public static final class CompileMessage extends
+ com.google.protobuf.GeneratedMessageLite
+ implements CompileMessageOrBuilder {
+ // Use CompileMessage.newBuilder() to construct.
+ private CompileMessage(Builder builder) {
+ super(builder);
+ }
+ private CompileMessage(boolean noInit) {}
+
+ private static final CompileMessage defaultInstance;
+ public static CompileMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public CompileMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Kind
+ implements com.google.protobuf.Internal.EnumLite {
+ ERROR(0, 1),
+ WARNING(1, 2),
+ MANDATORY_WARNING(2, 3),
+ NOTE(3, 4),
+ OTHER(4, 5),
+ STD_OUT(5, 6),
+ ;
+
+ public static final int ERROR_VALUE = 1;
+ public static final int WARNING_VALUE = 2;
+ public static final int MANDATORY_WARNING_VALUE = 3;
+ public static final int NOTE_VALUE = 4;
+ public static final int OTHER_VALUE = 5;
+ public static final int STD_OUT_VALUE = 6;
+
+
+ public final int getNumber() { return value; }
+
+ public static Kind valueOf(int value) {
+ switch (value) {
+ case 1: return ERROR;
+ case 2: return WARNING;
+ case 3: return MANDATORY_WARNING;
+ case 4: return NOTE;
+ case 5: return OTHER;
+ case 6: return STD_OUT;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Kind>() {
+ public Kind findValueByNumber(int number) {
+ return Kind.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Kind(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.javac.Message.Response.CompileMessage.Kind)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.javac.Message.Response.CompileMessage.Kind kind = 1;
+ public static final int KIND_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind kind_;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind getKind() {
+ return kind_;
+ }
+
+ // optional string text = 2;
+ public static final int TEXT_FIELD_NUMBER = 2;
+ private java.lang.Object text_;
+ public boolean hasText() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getText() {
+ java.lang.Object ref = text_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ text_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getTextBytes() {
+ java.lang.Object ref = text_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ text_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string source_uri = 3;
+ public static final int SOURCE_URI_FIELD_NUMBER = 3;
+ private java.lang.Object sourceUri_;
+ public boolean hasSourceUri() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getSourceUri() {
+ java.lang.Object ref = sourceUri_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ sourceUri_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getSourceUriBytes() {
+ java.lang.Object ref = sourceUri_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ sourceUri_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional uint64 problem_begin_offset = 4;
+ public static final int PROBLEM_BEGIN_OFFSET_FIELD_NUMBER = 4;
+ private long problemBeginOffset_;
+ public boolean hasProblemBeginOffset() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public long getProblemBeginOffset() {
+ return problemBeginOffset_;
+ }
+
+ // optional uint64 problem_end_offset = 5;
+ public static final int PROBLEM_END_OFFSET_FIELD_NUMBER = 5;
+ private long problemEndOffset_;
+ public boolean hasProblemEndOffset() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public long getProblemEndOffset() {
+ return problemEndOffset_;
+ }
+
+ // optional uint64 problem_location_offset = 6;
+ public static final int PROBLEM_LOCATION_OFFSET_FIELD_NUMBER = 6;
+ private long problemLocationOffset_;
+ public boolean hasProblemLocationOffset() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public long getProblemLocationOffset() {
+ return problemLocationOffset_;
+ }
+
+ // optional uint64 line = 7;
+ public static final int LINE_FIELD_NUMBER = 7;
+ private long line_;
+ public boolean hasLine() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public long getLine() {
+ return line_;
+ }
+
+ // optional uint64 column = 8;
+ public static final int COLUMN_FIELD_NUMBER = 8;
+ private long column_;
+ public boolean hasColumn() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ public long getColumn() {
+ return column_;
+ }
+
+ private void initFields() {
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind.ERROR;
+ text_ = "";
+ sourceUri_ = "";
+ problemBeginOffset_ = 0L;
+ problemEndOffset_ = 0L;
+ problemLocationOffset_ = 0L;
+ line_ = 0L;
+ column_ = 0L;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasKind()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getTextBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getSourceUriBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeUInt64(4, problemBeginOffset_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeUInt64(5, problemEndOffset_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeUInt64(6, problemLocationOffset_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output.writeUInt64(7, line_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ output.writeUInt64(8, column_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getTextBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getSourceUriBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(4, problemBeginOffset_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(5, problemEndOffset_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(6, problemLocationOffset_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(7, line_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(8, column_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessageOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind.ERROR;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ text_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ sourceUri_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ problemBeginOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ problemEndOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ problemLocationOffset_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ line_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ column_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000080);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.kind_ = kind_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.text_ = text_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.sourceUri_ = sourceUri_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.problemBeginOffset_ = problemBeginOffset_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.problemEndOffset_ = problemEndOffset_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.problemLocationOffset_ = problemLocationOffset_;
+ if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+ to_bitField0_ |= 0x00000040;
+ }
+ result.line_ = line_;
+ if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+ to_bitField0_ |= 0x00000080;
+ }
+ result.column_ = column_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance()) return this;
+ if (other.hasKind()) {
+ setKind(other.getKind());
+ }
+ if (other.hasText()) {
+ setText(other.getText());
+ }
+ if (other.hasSourceUri()) {
+ setSourceUri(other.getSourceUri());
+ }
+ if (other.hasProblemBeginOffset()) {
+ setProblemBeginOffset(other.getProblemBeginOffset());
+ }
+ if (other.hasProblemEndOffset()) {
+ setProblemEndOffset(other.getProblemEndOffset());
+ }
+ if (other.hasProblemLocationOffset()) {
+ setProblemLocationOffset(other.getProblemLocationOffset());
+ }
+ if (other.hasLine()) {
+ setLine(other.getLine());
+ }
+ if (other.hasColumn()) {
+ setColumn(other.getColumn());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasKind()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind value = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+ }
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ text_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ sourceUri_ = input.readBytes();
+ break;
+ }
+ case 32: {
+ bitField0_ |= 0x00000008;
+ problemBeginOffset_ = input.readUInt64();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ problemEndOffset_ = input.readUInt64();
+ break;
+ }
+ case 48: {
+ bitField0_ |= 0x00000020;
+ problemLocationOffset_ = input.readUInt64();
+ break;
+ }
+ case 56: {
+ bitField0_ |= 0x00000040;
+ line_ = input.readUInt64();
+ break;
+ }
+ case 64: {
+ bitField0_ |= 0x00000080;
+ column_ = input.readUInt64();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.javac.Message.Response.CompileMessage.Kind kind = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind.ERROR;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind getKind() {
+ return kind_;
+ }
+ public Builder setKind(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+
+ return this;
+ }
+ public Builder clearKind() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Kind.ERROR;
+
+ return this;
+ }
+
+ // optional string text = 2;
+ private java.lang.Object text_ = "";
+ public boolean hasText() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getText() {
+ java.lang.Object ref = text_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ text_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setText(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ text_ = value;
+
+ return this;
+ }
+ public Builder clearText() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ text_ = getDefaultInstance().getText();
+
+ return this;
+ }
+ void setText(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ text_ = value;
+
+ }
+
+ // optional string source_uri = 3;
+ private java.lang.Object sourceUri_ = "";
+ public boolean hasSourceUri() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getSourceUri() {
+ java.lang.Object ref = sourceUri_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ sourceUri_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setSourceUri(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ sourceUri_ = value;
+
+ return this;
+ }
+ public Builder clearSourceUri() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ sourceUri_ = getDefaultInstance().getSourceUri();
+
+ return this;
+ }
+ void setSourceUri(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ sourceUri_ = value;
+
+ }
+
+ // optional uint64 problem_begin_offset = 4;
+ private long problemBeginOffset_ ;
+ public boolean hasProblemBeginOffset() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public long getProblemBeginOffset() {
+ return problemBeginOffset_;
+ }
+ public Builder setProblemBeginOffset(long value) {
+ bitField0_ |= 0x00000008;
+ problemBeginOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemBeginOffset() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ problemBeginOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 problem_end_offset = 5;
+ private long problemEndOffset_ ;
+ public boolean hasProblemEndOffset() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public long getProblemEndOffset() {
+ return problemEndOffset_;
+ }
+ public Builder setProblemEndOffset(long value) {
+ bitField0_ |= 0x00000010;
+ problemEndOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemEndOffset() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ problemEndOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 problem_location_offset = 6;
+ private long problemLocationOffset_ ;
+ public boolean hasProblemLocationOffset() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public long getProblemLocationOffset() {
+ return problemLocationOffset_;
+ }
+ public Builder setProblemLocationOffset(long value) {
+ bitField0_ |= 0x00000020;
+ problemLocationOffset_ = value;
+
+ return this;
+ }
+ public Builder clearProblemLocationOffset() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ problemLocationOffset_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 line = 7;
+ private long line_ ;
+ public boolean hasLine() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public long getLine() {
+ return line_;
+ }
+ public Builder setLine(long value) {
+ bitField0_ |= 0x00000040;
+ line_ = value;
+
+ return this;
+ }
+ public Builder clearLine() {
+ bitField0_ = (bitField0_ & ~0x00000040);
+ line_ = 0L;
+
+ return this;
+ }
+
+ // optional uint64 column = 8;
+ private long column_ ;
+ public boolean hasColumn() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ public long getColumn() {
+ return column_;
+ }
+ public Builder setColumn(long value) {
+ bitField0_ |= 0x00000080;
+ column_ = value;
+
+ return this;
+ }
+ public Builder clearColumn() {
+ bitField0_ = (bitField0_ & ~0x00000080);
+ column_ = 0L;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response.CompileMessage)
+ }
+
+ static {
+ defaultInstance = new CompileMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.CompileMessage)
+ }
+
+ public interface OutputObjectOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required .org.jetbrains.javac.Message.Response.OutputObject.Kind kind = 1;
+ boolean hasKind();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind getKind();
+
+ // required string file_path = 2;
+ boolean hasFilePath();
+ String getFilePath();
+
+ // optional string output_root = 3;
+ boolean hasOutputRoot();
+ String getOutputRoot();
+
+ // optional string relative_path = 4;
+ boolean hasRelativePath();
+ String getRelativePath();
+
+ // optional string class_name = 5;
+ boolean hasClassName();
+ String getClassName();
+
+ // optional string source_uri = 6;
+ boolean hasSourceUri();
+ String getSourceUri();
+
+ // optional bytes content = 7;
+ boolean hasContent();
+ com.google.protobuf.ByteString getContent();
+ }
+ public static final class OutputObject extends
+ com.google.protobuf.GeneratedMessageLite
+ implements OutputObjectOrBuilder {
+ // Use OutputObject.newBuilder() to construct.
+ private OutputObject(Builder builder) {
+ super(builder);
+ }
+ private OutputObject(boolean noInit) {}
+
+ private static final OutputObject defaultInstance;
+ public static OutputObject getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public OutputObject getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public enum Kind
+ implements com.google.protobuf.Internal.EnumLite {
+ SOURCE(0, 1),
+ CLASS(1, 2),
+ HTML(2, 3),
+ OTHER(3, 4),
+ ;
+
+ public static final int SOURCE_VALUE = 1;
+ public static final int CLASS_VALUE = 2;
+ public static final int HTML_VALUE = 3;
+ public static final int OTHER_VALUE = 4;
+
+
+ public final int getNumber() { return value; }
+
+ public static Kind valueOf(int value) {
+ switch (value) {
+ case 1: return SOURCE;
+ case 2: return CLASS;
+ case 3: return HTML;
+ case 4: return OTHER;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap<Kind>
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap<Kind>() {
+ public Kind findValueByNumber(int number) {
+ return Kind.valueOf(number);
+ }
+ };
+
+ private final int value;
+
+ private Kind(int index, int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:org.jetbrains.javac.Message.Response.OutputObject.Kind)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.javac.Message.Response.OutputObject.Kind kind = 1;
+ public static final int KIND_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind kind_;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind getKind() {
+ return kind_;
+ }
+
+ // required string file_path = 2;
+ public static final int FILE_PATH_FIELD_NUMBER = 2;
+ private java.lang.Object filePath_;
+ public boolean hasFilePath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFilePath() {
+ java.lang.Object ref = filePath_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ filePath_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getFilePathBytes() {
+ java.lang.Object ref = filePath_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ filePath_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string output_root = 3;
+ public static final int OUTPUT_ROOT_FIELD_NUMBER = 3;
+ private java.lang.Object outputRoot_;
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ outputRoot_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getOutputRootBytes() {
+ java.lang.Object ref = outputRoot_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ outputRoot_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string relative_path = 4;
+ public static final int RELATIVE_PATH_FIELD_NUMBER = 4;
+ private java.lang.Object relativePath_;
+ public boolean hasRelativePath() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public String getRelativePath() {
+ java.lang.Object ref = relativePath_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ relativePath_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getRelativePathBytes() {
+ java.lang.Object ref = relativePath_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ relativePath_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string class_name = 5;
+ public static final int CLASS_NAME_FIELD_NUMBER = 5;
+ private java.lang.Object className_;
+ public boolean hasClassName() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public String getClassName() {
+ java.lang.Object ref = className_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ className_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getClassNameBytes() {
+ java.lang.Object ref = className_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ className_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string source_uri = 6;
+ public static final int SOURCE_URI_FIELD_NUMBER = 6;
+ private java.lang.Object sourceUri_;
+ public boolean hasSourceUri() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public String getSourceUri() {
+ java.lang.Object ref = sourceUri_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ sourceUri_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getSourceUriBytes() {
+ java.lang.Object ref = sourceUri_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ sourceUri_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional bytes content = 7;
+ public static final int CONTENT_FIELD_NUMBER = 7;
+ private com.google.protobuf.ByteString content_;
+ public boolean hasContent() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public com.google.protobuf.ByteString getContent() {
+ return content_;
+ }
+
+ private void initFields() {
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind.SOURCE;
+ filePath_ = "";
+ outputRoot_ = "";
+ relativePath_ = "";
+ className_ = "";
+ sourceUri_ = "";
+ content_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasKind()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasFilePath()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getFilePathBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getOutputRootBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, getRelativePathBytes());
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBytes(5, getClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeBytes(6, getSourceUriBytes());
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output.writeBytes(7, content_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, kind_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getFilePathBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getOutputRootBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, getRelativePathBytes());
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(5, getClassNameBytes());
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(6, getSourceUriBytes());
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(7, content_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObjectOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind.SOURCE;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ filePath_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ outputRoot_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ relativePath_ = "";
+ bitField0_ = (bitField0_ & ~0x00000008);
+ className_ = "";
+ bitField0_ = (bitField0_ & ~0x00000010);
+ sourceUri_ = "";
+ bitField0_ = (bitField0_ & ~0x00000020);
+ content_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.kind_ = kind_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.filePath_ = filePath_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.outputRoot_ = outputRoot_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.relativePath_ = relativePath_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.className_ = className_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.sourceUri_ = sourceUri_;
+ if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+ to_bitField0_ |= 0x00000040;
+ }
+ result.content_ = content_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance()) return this;
+ if (other.hasKind()) {
+ setKind(other.getKind());
+ }
+ if (other.hasFilePath()) {
+ setFilePath(other.getFilePath());
+ }
+ if (other.hasOutputRoot()) {
+ setOutputRoot(other.getOutputRoot());
+ }
+ if (other.hasRelativePath()) {
+ setRelativePath(other.getRelativePath());
+ }
+ if (other.hasClassName()) {
+ setClassName(other.getClassName());
+ }
+ if (other.hasSourceUri()) {
+ setSourceUri(other.getSourceUri());
+ }
+ if (other.hasContent()) {
+ setContent(other.getContent());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasKind()) {
+
+ return false;
+ }
+ if (!hasFilePath()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind value = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+ }
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ filePath_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ outputRoot_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ relativePath_ = input.readBytes();
+ break;
+ }
+ case 42: {
+ bitField0_ |= 0x00000010;
+ className_ = input.readBytes();
+ break;
+ }
+ case 50: {
+ bitField0_ |= 0x00000020;
+ sourceUri_ = input.readBytes();
+ break;
+ }
+ case 58: {
+ bitField0_ |= 0x00000040;
+ content_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.javac.Message.Response.OutputObject.Kind kind = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind.SOURCE;
+ public boolean hasKind() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind getKind() {
+ return kind_;
+ }
+ public Builder setKind(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ kind_ = value;
+
+ return this;
+ }
+ public Builder clearKind() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ kind_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Kind.SOURCE;
+
+ return this;
+ }
+
+ // required string file_path = 2;
+ private java.lang.Object filePath_ = "";
+ public boolean hasFilePath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public String getFilePath() {
+ java.lang.Object ref = filePath_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ filePath_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setFilePath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ filePath_ = value;
+
+ return this;
+ }
+ public Builder clearFilePath() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ filePath_ = getDefaultInstance().getFilePath();
+
+ return this;
+ }
+ void setFilePath(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ filePath_ = value;
+
+ }
+
+ // optional string output_root = 3;
+ private java.lang.Object outputRoot_ = "";
+ public boolean hasOutputRoot() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public String getOutputRoot() {
+ java.lang.Object ref = outputRoot_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ outputRoot_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setOutputRoot(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ outputRoot_ = value;
+
+ return this;
+ }
+ public Builder clearOutputRoot() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ outputRoot_ = getDefaultInstance().getOutputRoot();
+
+ return this;
+ }
+ void setOutputRoot(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000004;
+ outputRoot_ = value;
+
+ }
+
+ // optional string relative_path = 4;
+ private java.lang.Object relativePath_ = "";
+ public boolean hasRelativePath() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public String getRelativePath() {
+ java.lang.Object ref = relativePath_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ relativePath_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setRelativePath(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ relativePath_ = value;
+
+ return this;
+ }
+ public Builder clearRelativePath() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ relativePath_ = getDefaultInstance().getRelativePath();
+
+ return this;
+ }
+ void setRelativePath(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000008;
+ relativePath_ = value;
+
+ }
+
+ // optional string class_name = 5;
+ private java.lang.Object className_ = "";
+ public boolean hasClassName() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public String getClassName() {
+ java.lang.Object ref = className_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ className_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setClassName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
+ className_ = value;
+
+ return this;
+ }
+ public Builder clearClassName() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ className_ = getDefaultInstance().getClassName();
+
+ return this;
+ }
+ void setClassName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000010;
+ className_ = value;
+
+ }
+
+ // optional string source_uri = 6;
+ private java.lang.Object sourceUri_ = "";
+ public boolean hasSourceUri() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ public String getSourceUri() {
+ java.lang.Object ref = sourceUri_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ sourceUri_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setSourceUri(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000020;
+ sourceUri_ = value;
+
+ return this;
+ }
+ public Builder clearSourceUri() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ sourceUri_ = getDefaultInstance().getSourceUri();
+
+ return this;
+ }
+ void setSourceUri(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000020;
+ sourceUri_ = value;
+
+ }
+
+ // optional bytes content = 7;
+ private com.google.protobuf.ByteString content_ = com.google.protobuf.ByteString.EMPTY;
+ public boolean hasContent() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ public com.google.protobuf.ByteString getContent() {
+ return content_;
+ }
+ public Builder setContent(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000040;
+ content_ = value;
+
+ return this;
+ }
+ public Builder clearContent() {
+ bitField0_ = (bitField0_ & ~0x00000040);
+ content_ = getDefaultInstance().getContent();
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response.OutputObject)
+ }
+
+ static {
+ defaultInstance = new OutputObject(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.OutputObject)
+ }
+
+ public interface ClassDataOrBuilder
+ extends com.google.protobuf.MessageLiteOrBuilder {
+
+ // required string class_name = 1;
+ boolean hasClassName();
+ String getClassName();
+
+ // repeated string import_statement = 2;
+ java.util.List<String> getImportStatementList();
+ int getImportStatementCount();
+ String getImportStatement(int index);
+
+ // repeated string static_import = 3;
+ java.util.List<String> getStaticImportList();
+ int getStaticImportCount();
+ String getStaticImport(int index);
+
+ // repeated string identifier = 4;
+ java.util.List<String> getIdentifierList();
+ int getIdentifierCount();
+ String getIdentifier(int index);
+ }
+ public static final class ClassData extends
+ com.google.protobuf.GeneratedMessageLite
+ implements ClassDataOrBuilder {
+ // Use ClassData.newBuilder() to construct.
+ private ClassData(Builder builder) {
+ super(builder);
+ }
+ private ClassData(boolean noInit) {}
+
+ private static final ClassData defaultInstance;
+ public static ClassData getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ClassData getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private int bitField0_;
+ // required string class_name = 1;
+ public static final int CLASS_NAME_FIELD_NUMBER = 1;
+ private java.lang.Object className_;
+ public boolean hasClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getClassName() {
+ java.lang.Object ref = className_;
+ if (ref instanceof String) {
+ return (String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ String s = bs.toStringUtf8();
+ if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+ className_ = s;
+ }
+ return s;
+ }
+ }
+ private com.google.protobuf.ByteString getClassNameBytes() {
+ java.lang.Object ref = className_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+ className_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // repeated string import_statement = 2;
+ public static final int IMPORT_STATEMENT_FIELD_NUMBER = 2;
+ private com.google.protobuf.LazyStringList importStatement_;
+ public java.util.List<String>
+ getImportStatementList() {
+ return importStatement_;
+ }
+ public int getImportStatementCount() {
+ return importStatement_.size();
+ }
+ public String getImportStatement(int index) {
+ return importStatement_.get(index);
+ }
+
+ // repeated string static_import = 3;
+ public static final int STATIC_IMPORT_FIELD_NUMBER = 3;
+ private com.google.protobuf.LazyStringList staticImport_;
+ public java.util.List<String>
+ getStaticImportList() {
+ return staticImport_;
+ }
+ public int getStaticImportCount() {
+ return staticImport_.size();
+ }
+ public String getStaticImport(int index) {
+ return staticImport_.get(index);
+ }
+
+ // repeated string identifier = 4;
+ public static final int IDENTIFIER_FIELD_NUMBER = 4;
+ private com.google.protobuf.LazyStringList identifier_;
+ public java.util.List<String>
+ getIdentifierList() {
+ return identifier_;
+ }
+ public int getIdentifierCount() {
+ return identifier_.size();
+ }
+ public String getIdentifier(int index) {
+ return identifier_.get(index);
+ }
+
+ private void initFields() {
+ className_ = "";
+ importStatement_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ staticImport_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ identifier_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasClassName()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getClassNameBytes());
+ }
+ for (int i = 0; i < importStatement_.size(); i++) {
+ output.writeBytes(2, importStatement_.getByteString(i));
+ }
+ for (int i = 0; i < staticImport_.size(); i++) {
+ output.writeBytes(3, staticImport_.getByteString(i));
+ }
+ for (int i = 0; i < identifier_.size(); i++) {
+ output.writeBytes(4, identifier_.getByteString(i));
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getClassNameBytes());
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < importStatement_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(importStatement_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getImportStatementList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < staticImport_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(staticImport_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getStaticImportList().size();
+ }
+ {
+ int dataSize = 0;
+ for (int i = 0; i < identifier_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(identifier_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getIdentifierList().size();
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassDataOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ className_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ importStatement_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ staticImport_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ identifier_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.className_ = className_;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ importStatement_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ importStatement_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.importStatement_ = importStatement_;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ staticImport_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ staticImport_);
+ bitField0_ = (bitField0_ & ~0x00000004);
+ }
+ result.staticImport_ = staticImport_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ identifier_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ identifier_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.identifier_ = identifier_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) return this;
+ if (other.hasClassName()) {
+ setClassName(other.getClassName());
+ }
+ if (!other.importStatement_.isEmpty()) {
+ if (importStatement_.isEmpty()) {
+ importStatement_ = other.importStatement_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensureImportStatementIsMutable();
+ importStatement_.addAll(other.importStatement_);
+ }
+
+ }
+ if (!other.staticImport_.isEmpty()) {
+ if (staticImport_.isEmpty()) {
+ staticImport_ = other.staticImport_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureStaticImportIsMutable();
+ staticImport_.addAll(other.staticImport_);
+ }
+
+ }
+ if (!other.identifier_.isEmpty()) {
+ if (identifier_.isEmpty()) {
+ identifier_ = other.identifier_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureIdentifierIsMutable();
+ identifier_.addAll(other.identifier_);
+ }
+
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasClassName()) {
+
+ return false;
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ className_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ ensureImportStatementIsMutable();
+ importStatement_.add(input.readBytes());
+ break;
+ }
+ case 26: {
+ ensureStaticImportIsMutable();
+ staticImport_.add(input.readBytes());
+ break;
+ }
+ case 34: {
+ ensureIdentifierIsMutable();
+ identifier_.add(input.readBytes());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required string class_name = 1;
+ private java.lang.Object className_ = "";
+ public boolean hasClassName() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public String getClassName() {
+ java.lang.Object ref = className_;
+ if (!(ref instanceof String)) {
+ String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+ className_ = s;
+ return s;
+ } else {
+ return (String) ref;
+ }
+ }
+ public Builder setClassName(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ className_ = value;
+
+ return this;
+ }
+ public Builder clearClassName() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ className_ = getDefaultInstance().getClassName();
+
+ return this;
+ }
+ void setClassName(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000001;
+ className_ = value;
+
+ }
+
+ // repeated string import_statement = 2;
+ private com.google.protobuf.LazyStringList importStatement_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureImportStatementIsMutable() {
+ if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+ importStatement_ = new com.google.protobuf.LazyStringArrayList(importStatement_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+ public java.util.List<String>
+ getImportStatementList() {
+ return java.util.Collections.unmodifiableList(importStatement_);
+ }
+ public int getImportStatementCount() {
+ return importStatement_.size();
+ }
+ public String getImportStatement(int index) {
+ return importStatement_.get(index);
+ }
+ public Builder setImportStatement(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureImportStatementIsMutable();
+ importStatement_.set(index, value);
+
+ return this;
+ }
+ public Builder addImportStatement(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureImportStatementIsMutable();
+ importStatement_.add(value);
+
+ return this;
+ }
+ public Builder addAllImportStatement(
+ java.lang.Iterable<String> values) {
+ ensureImportStatementIsMutable();
+ super.addAll(values, importStatement_);
+
+ return this;
+ }
+ public Builder clearImportStatement() {
+ importStatement_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+
+ return this;
+ }
+ void addImportStatement(com.google.protobuf.ByteString value) {
+ ensureImportStatementIsMutable();
+ importStatement_.add(value);
+
+ }
+
+ // repeated string static_import = 3;
+ private com.google.protobuf.LazyStringList staticImport_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureStaticImportIsMutable() {
+ if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+ staticImport_ = new com.google.protobuf.LazyStringArrayList(staticImport_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+ public java.util.List<String>
+ getStaticImportList() {
+ return java.util.Collections.unmodifiableList(staticImport_);
+ }
+ public int getStaticImportCount() {
+ return staticImport_.size();
+ }
+ public String getStaticImport(int index) {
+ return staticImport_.get(index);
+ }
+ public Builder setStaticImport(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureStaticImportIsMutable();
+ staticImport_.set(index, value);
+
+ return this;
+ }
+ public Builder addStaticImport(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureStaticImportIsMutable();
+ staticImport_.add(value);
+
+ return this;
+ }
+ public Builder addAllStaticImport(
+ java.lang.Iterable<String> values) {
+ ensureStaticImportIsMutable();
+ super.addAll(values, staticImport_);
+
+ return this;
+ }
+ public Builder clearStaticImport() {
+ staticImport_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+
+ return this;
+ }
+ void addStaticImport(com.google.protobuf.ByteString value) {
+ ensureStaticImportIsMutable();
+ staticImport_.add(value);
+
+ }
+
+ // repeated string identifier = 4;
+ private com.google.protobuf.LazyStringList identifier_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureIdentifierIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ identifier_ = new com.google.protobuf.LazyStringArrayList(identifier_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+ public java.util.List<String>
+ getIdentifierList() {
+ return java.util.Collections.unmodifiableList(identifier_);
+ }
+ public int getIdentifierCount() {
+ return identifier_.size();
+ }
+ public String getIdentifier(int index) {
+ return identifier_.get(index);
+ }
+ public Builder setIdentifier(
+ int index, String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureIdentifierIsMutable();
+ identifier_.set(index, value);
+
+ return this;
+ }
+ public Builder addIdentifier(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureIdentifierIsMutable();
+ identifier_.add(value);
+
+ return this;
+ }
+ public Builder addAllIdentifier(
+ java.lang.Iterable<String> values) {
+ ensureIdentifierIsMutable();
+ super.addAll(values, identifier_);
+
+ return this;
+ }
+ public Builder clearIdentifier() {
+ identifier_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+
+ return this;
+ }
+ void addIdentifier(com.google.protobuf.ByteString value) {
+ ensureIdentifierIsMutable();
+ identifier_.add(value);
+
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response.ClassData)
+ }
+
+ static {
+ defaultInstance = new ClassData(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.ClassData)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.javac.Message.Response.Type response_type = 1;
+ public static final int RESPONSE_TYPE_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type responseType_;
+ public boolean hasResponseType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type getResponseType() {
+ return responseType_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.CompileMessage compile_message = 2;
+ public static final int COMPILE_MESSAGE_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage compileMessage_;
+ public boolean hasCompileMessage() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage getCompileMessage() {
+ return compileMessage_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.OutputObject output_object = 3;
+ public static final int OUTPUT_OBJECT_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject outputObject_;
+ public boolean hasOutputObject() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getOutputObject() {
+ return outputObject_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4;
+ public static final int CLASS_DATA_FIELD_NUMBER = 4;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData classData_;
+ public boolean hasClassData() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() {
+ return classData_;
+ }
+
+ // optional bool completion_status = 5;
+ public static final int COMPLETION_STATUS_FIELD_NUMBER = 5;
+ private boolean completionStatus_;
+ public boolean hasCompletionStatus() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public boolean getCompletionStatus() {
+ return completionStatus_;
+ }
+
+ private void initFields() {
+ responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE;
+ compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance();
+ outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance();
+ classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance();
+ completionStatus_ = false;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasResponseType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasCompileMessage()) {
+ if (!getCompileMessage().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasOutputObject()) {
+ if (!getOutputObject().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasClassData()) {
+ if (!getClassData().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, responseType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, compileMessage_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, outputObject_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(4, classData_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBool(5, completionStatus_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, responseType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, compileMessage_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, outputObject_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, classData_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(5, completionStatus_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.Message.ResponseOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ completionStatus_ = false;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.responseType_ = responseType_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.compileMessage_ = compileMessage_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.outputObject_ = outputObject_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.classData_ = classData_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.completionStatus_ = completionStatus_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance()) return this;
+ if (other.hasResponseType()) {
+ setResponseType(other.getResponseType());
+ }
+ if (other.hasCompileMessage()) {
+ mergeCompileMessage(other.getCompileMessage());
+ }
+ if (other.hasOutputObject()) {
+ mergeOutputObject(other.getOutputObject());
+ }
+ if (other.hasClassData()) {
+ mergeClassData(other.getClassData());
+ }
+ if (other.hasCompletionStatus()) {
+ setCompletionStatus(other.getCompletionStatus());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasResponseType()) {
+
+ return false;
+ }
+ if (hasCompileMessage()) {
+ if (!getCompileMessage().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasOutputObject()) {
+ if (!getOutputObject().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasClassData()) {
+ if (!getClassData().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type value = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000001;
+ responseType_ = value;
+ }
+ break;
+ }
+ case 18: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.newBuilder();
+ if (hasCompileMessage()) {
+ subBuilder.mergeFrom(getCompileMessage());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setCompileMessage(subBuilder.buildPartial());
+ break;
+ }
+ case 26: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.newBuilder();
+ if (hasOutputObject()) {
+ subBuilder.mergeFrom(getOutputObject());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setOutputObject(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder();
+ if (hasClassData()) {
+ subBuilder.mergeFrom(getClassData());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setClassData(subBuilder.buildPartial());
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ completionStatus_ = input.readBool();
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.javac.Message.Response.Type response_type = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE;
+ public boolean hasResponseType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type getResponseType() {
+ return responseType_;
+ }
+ public Builder setResponseType(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ responseType_ = value;
+
+ return this;
+ }
+ public Builder clearResponseType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.CompileMessage compile_message = 2;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance();
+ public boolean hasCompileMessage() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage getCompileMessage() {
+ return compileMessage_;
+ }
+ public Builder setCompileMessage(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ compileMessage_ = value;
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder setCompileMessage(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.Builder builderForValue) {
+ compileMessage_ = builderForValue.build();
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder mergeCompileMessage(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage value) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ compileMessage_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance()) {
+ compileMessage_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.newBuilder(compileMessage_).mergeFrom(value).buildPartial();
+ } else {
+ compileMessage_ = value;
+ }
+
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ public Builder clearCompileMessage() {
+ compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.OutputObject output_object = 3;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance();
+ public boolean hasOutputObject() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getOutputObject() {
+ return outputObject_;
+ }
+ public Builder setOutputObject(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ outputObject_ = value;
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder setOutputObject(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.Builder builderForValue) {
+ outputObject_ = builderForValue.build();
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder mergeOutputObject(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject value) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ outputObject_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance()) {
+ outputObject_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.newBuilder(outputObject_).mergeFrom(value).buildPartial();
+ } else {
+ outputObject_ = value;
+ }
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder clearOutputObject() {
+ outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance();
+ public boolean hasClassData() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() {
+ return classData_;
+ }
+ public Builder setClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ classData_ = value;
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder setClassData(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder builderForValue) {
+ classData_ = builderForValue.build();
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder mergeClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) {
+ if (((bitField0_ & 0x00000008) == 0x00000008) &&
+ classData_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) {
+ classData_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder(classData_).mergeFrom(value).buildPartial();
+ } else {
+ classData_ = value;
+ }
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder clearClassData() {
+ classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ // optional bool completion_status = 5;
+ private boolean completionStatus_ ;
+ public boolean hasCompletionStatus() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public boolean getCompletionStatus() {
+ return completionStatus_;
+ }
+ public Builder setCompletionStatus(boolean value) {
+ bitField0_ |= 0x00000010;
+ completionStatus_ = value;
+
+ return this;
+ }
+ public Builder clearCompletionStatus() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ completionStatus_ = false;
+
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response)
+ }
+
+ static {
+ defaultInstance = new Response(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response)
+ }
+
+ private int bitField0_;
+ // required .org.jetbrains.javac.Message.UUID session_id = 1;
+ public static final int SESSION_ID_FIELD_NUMBER = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID sessionId_;
+ public boolean hasSessionId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID getSessionId() {
+ return sessionId_;
+ }
+
+ // required .org.jetbrains.javac.Message.Type message_type = 2;
+ public static final int MESSAGE_TYPE_FIELD_NUMBER = 2;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Type messageType_;
+ public boolean hasMessageType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Type getMessageType() {
+ return messageType_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Request request = 3;
+ public static final int REQUEST_FIELD_NUMBER = 3;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request request_;
+ public boolean hasRequest() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request getRequest() {
+ return request_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response response = 4;
+ public static final int RESPONSE_FIELD_NUMBER = 4;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response response_;
+ public boolean hasResponse() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response getResponse() {
+ return response_;
+ }
+
+ // optional .org.jetbrains.javac.Message.Failure failure = 5;
+ public static final int FAILURE_FIELD_NUMBER = 5;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure failure_;
+ public boolean hasFailure() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure getFailure() {
+ return failure_;
+ }
+
+ private void initFields() {
+ sessionId_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance();
+ messageType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Type.REQUEST;
+ request_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance();
+ response_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance();
+ failure_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ if (!hasSessionId()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!hasMessageType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (!getSessionId().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ if (hasRequest()) {
+ if (!getRequest().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ if (hasResponse()) {
+ if (!getResponse().isInitialized()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
+ }
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeMessage(1, sessionId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeEnum(2, messageType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, request_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeMessage(4, response_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeMessage(5, failure_);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, sessionId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(2, messageType_.getNumber());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, request_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, response_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(5, failure_);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static org.jetbrains.jps.javac.JavacRemoteProto.Message parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ org.jetbrains.jps.javac.JavacRemoteProto.Message, Builder>
+ implements org.jetbrains.jps.javac.JavacRemoteProto.MessageOrBuilder {
+ // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ sessionId_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ messageType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Type.REQUEST;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ request_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ response_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ failure_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance();
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message getDefaultInstanceForType() {
+ return org.jetbrains.jps.javac.JavacRemoteProto.Message.getDefaultInstance();
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message build() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return result;
+ }
+
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message buildPartial() {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message result = new org.jetbrains.jps.javac.JavacRemoteProto.Message(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.sessionId_ = sessionId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.messageType_ = messageType_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.request_ = request_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.response_ = response_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.failure_ = failure_;
+ result.bitField0_ = to_bitField0_;
+ return result;
+ }
+
+ public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message other) {
+ if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.getDefaultInstance()) return this;
+ if (other.hasSessionId()) {
+ mergeSessionId(other.getSessionId());
+ }
+ if (other.hasMessageType()) {
+ setMessageType(other.getMessageType());
+ }
+ if (other.hasRequest()) {
+ mergeRequest(other.getRequest());
+ }
+ if (other.hasResponse()) {
+ mergeResponse(other.getResponse());
+ }
+ if (other.hasFailure()) {
+ mergeFailure(other.getFailure());
+ }
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ if (!hasSessionId()) {
+
+ return false;
+ }
+ if (!hasMessageType()) {
+
+ return false;
+ }
+ if (!getSessionId().isInitialized()) {
+
+ return false;
+ }
+ if (hasRequest()) {
+ if (!getRequest().isInitialized()) {
+
+ return false;
+ }
+ }
+ if (hasResponse()) {
+ if (!getResponse().isInitialized()) {
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.newBuilder();
+ if (hasSessionId()) {
+ subBuilder.mergeFrom(getSessionId());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setSessionId(subBuilder.buildPartial());
+ break;
+ }
+ case 16: {
+ int rawValue = input.readEnum();
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Type value = org.jetbrains.jps.javac.JavacRemoteProto.Message.Type.valueOf(rawValue);
+ if (value != null) {
+ bitField0_ |= 0x00000002;
+ messageType_ = value;
+ }
+ break;
+ }
+ case 26: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.newBuilder();
+ if (hasRequest()) {
+ subBuilder.mergeFrom(getRequest());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setRequest(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.newBuilder();
+ if (hasResponse()) {
+ subBuilder.mergeFrom(getResponse());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setResponse(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.newBuilder();
+ if (hasFailure()) {
+ subBuilder.mergeFrom(getFailure());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setFailure(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+ private int bitField0_;
+
+ // required .org.jetbrains.javac.Message.UUID session_id = 1;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID sessionId_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance();
+ public boolean hasSessionId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID getSessionId() {
+ return sessionId_;
+ }
+ public Builder setSessionId(org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ sessionId_ = value;
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder setSessionId(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.Builder builderForValue) {
+ sessionId_ = builderForValue.build();
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder mergeSessionId(org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID value) {
+ if (((bitField0_ & 0x00000001) == 0x00000001) &&
+ sessionId_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance()) {
+ sessionId_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.newBuilder(sessionId_).mergeFrom(value).buildPartial();
+ } else {
+ sessionId_ = value;
+ }
+
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ public Builder clearSessionId() {
+ sessionId_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.UUID.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000001);
+ return this;
+ }
+
+ // required .org.jetbrains.javac.Message.Type message_type = 2;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Type messageType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Type.REQUEST;
+ public boolean hasMessageType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Type getMessageType() {
+ return messageType_;
+ }
+ public Builder setMessageType(org.jetbrains.jps.javac.JavacRemoteProto.Message.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ messageType_ = value;
+
+ return this;
+ }
+ public Builder clearMessageType() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ messageType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Type.REQUEST;
+
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Request request = 3;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Request request_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance();
+ public boolean hasRequest() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Request getRequest() {
+ return request_;
+ }
+ public Builder setRequest(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ request_ = value;
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder setRequest(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.Builder builderForValue) {
+ request_ = builderForValue.build();
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder mergeRequest(org.jetbrains.jps.javac.JavacRemoteProto.Message.Request value) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ request_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance()) {
+ request_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.newBuilder(request_).mergeFrom(value).buildPartial();
+ } else {
+ request_ = value;
+ }
+
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ public Builder clearRequest() {
+ request_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Request.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Response response = 4;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response response_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance();
+ public boolean hasResponse() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response getResponse() {
+ return response_;
+ }
+ public Builder setResponse(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ response_ = value;
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder setResponse(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Builder builderForValue) {
+ response_ = builderForValue.build();
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder mergeResponse(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response value) {
+ if (((bitField0_ & 0x00000008) == 0x00000008) &&
+ response_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance()) {
+ response_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.newBuilder(response_).mergeFrom(value).buildPartial();
+ } else {
+ response_ = value;
+ }
+
+ bitField0_ |= 0x00000008;
+ return this;
+ }
+ public Builder clearResponse() {
+ response_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ // optional .org.jetbrains.javac.Message.Failure failure = 5;
+ private org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure failure_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance();
+ public boolean hasFailure() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ public org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure getFailure() {
+ return failure_;
+ }
+ public Builder setFailure(org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ failure_ = value;
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder setFailure(
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.Builder builderForValue) {
+ failure_ = builderForValue.build();
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder mergeFailure(org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure value) {
+ if (((bitField0_ & 0x00000010) == 0x00000010) &&
+ failure_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance()) {
+ failure_ =
+ org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.newBuilder(failure_).mergeFrom(value).buildPartial();
+ } else {
+ failure_ = value;
+ }
+
+ bitField0_ |= 0x00000010;
+ return this;
+ }
+ public Builder clearFailure() {
+ failure_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Failure.getDefaultInstance();
+
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message)
+ }
+
+ static {
+ defaultInstance = new Message(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message)
+ }
+
+
+ static {
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
new file mode 100644
index 000000000000..de7d2a4577c0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.*;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.ChannelGroupFuture;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import javax.tools.*;
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/22/12
+ */
+public class JavacServer {
+ public static final int DEFAULT_SERVER_PORT = 7878;
+ public static final String SERVER_SUCCESS_START_MESSAGE = "Javac server started successfully. Listening on port: ";
+ public static final String SERVER_ERROR_START_MESSAGE = "Error starting Javac Server: ";
+
+ private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("javac-server");
+ private final ChannelFactory myChannelFactory;
+ private final ChannelPipelineFactory myPipelineFactory;
+
+ public JavacServer() {
+ myChannelFactory = new NioServerSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
+ final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
+ final ChannelHandler compilationRequestsHandler = new CompilationRequestsHandler();
+ myPipelineFactory = new ChannelPipelineFactory() {
+ public ChannelPipeline getPipeline() throws Exception {
+ return Channels.pipeline(
+ channelRegistrar,
+ new ProtobufVarint32FrameDecoder(),
+ new ProtobufDecoder(JavacRemoteProto.Message.getDefaultInstance()),
+ new ProtobufVarint32LengthFieldPrepender(),
+ new ProtobufEncoder(),
+ compilationRequestsHandler
+ );
+ }
+ };
+ }
+
+ public void start(int listenPort) {
+ final ServerBootstrap bootstrap = new ServerBootstrap(myChannelFactory);
+ bootstrap.setPipelineFactory(myPipelineFactory);
+ bootstrap.setOption("child.tcpNoDelay", true);
+ bootstrap.setOption("child.keepAlive", true);
+ final Channel serverChannel = bootstrap.bind(new InetSocketAddress(listenPort));
+ myAllOpenChannels.add(serverChannel);
+ }
+
+ public void stop() {
+ try {
+ final ChannelGroupFuture closeFuture = myAllOpenChannels.close();
+ closeFuture.awaitUninterruptibly();
+ }
+ finally {
+ myChannelFactory.releaseExternalResources();
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ int port = DEFAULT_SERVER_PORT;
+ if (args.length > 0) {
+ try {
+ port = Integer.parseInt(args[0]);
+ }
+ catch (NumberFormatException e) {
+ System.err.println("Error parsing port: " + e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+ final JavacServer server = new JavacServer();
+ server.start(port);
+ Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") {
+ public void run() {
+ server.stop();
+ }
+ });
+
+ System.out.println("Server classpath: " + System.getProperty("java.class.path"));
+ System.err.println(SERVER_SUCCESS_START_MESSAGE + port);
+ }
+ catch (Throwable e) {
+ System.err.println(SERVER_ERROR_START_MESSAGE + e.getMessage());
+ e.printStackTrace(System.err);
+ System.exit(-1);
+ }
+ }
+
+
+ public static JavacRemoteProto.Message compile(final ChannelHandlerContext ctx,
+ final UUID sessionId,
+ List<String> options,
+ Collection<File> files,
+ Collection<File> classpath,
+ Collection<File> platformCp,
+ Collection<File> sourcePath,
+ Map<File, Set<File>> outs,
+ final CanceledStatus canceledStatus) {
+ final DiagnosticOutputConsumer diagnostic = new DiagnosticOutputConsumer() {
+ public void outputLineAvailable(String line) {
+ Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createStdOutputResponse(line)));
+ }
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ final JavacRemoteProto.Message.Response response = JavacProtoUtil.createBuildMessageResponse(diagnostic);
+ Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response));
+ }
+
+ @Override
+ public void registerImports(String className, Collection<String> imports, Collection<String> staticImports) {
+ final JavacRemoteProto.Message.Response response = JavacProtoUtil.createClassDataResponse(className, imports, staticImports);
+ Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response));
+ }
+ };
+
+ final OutputFileConsumer outputSink = new OutputFileConsumer() {
+ public void save(@NotNull OutputFileObject fileObject) {
+ Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createOutputObjectResponse(fileObject)));
+ }
+ };
+
+ try {
+ final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus, false);
+ return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createBuildCompletedResponse(rc));
+ }
+ catch (Throwable e) {
+ e.printStackTrace(System.err);
+ return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createFailure(e.getMessage(), e));
+ }
+ }
+
+ private final Set<CancelHandler> myCancelHandlers = Collections.synchronizedSet(new HashSet<CancelHandler>());
+
+ public void cancelBuilds() {
+ synchronized (myCancelHandlers) {
+ for (CancelHandler handler : myCancelHandlers) {
+ handler.cancel();
+ }
+ }
+ }
+
+ private static List<File> toFiles(List<String> paths) {
+ final List<File> files = new ArrayList<File>(paths.size());
+ for (String path : paths) {
+ files.add(new File(path));
+ }
+ return files;
+ }
+
+ private class CompilationRequestsHandler extends SimpleChannelHandler {
+
+ public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ final JavacRemoteProto.Message msg = (JavacRemoteProto.Message)e.getMessage();
+ final UUID sessionId = JavacProtoUtil.fromProtoUUID(msg.getSessionId());
+ final JavacRemoteProto.Message.Type messageType = msg.getMessageType();
+
+ JavacRemoteProto.Message reply = null;
+
+ try {
+ if (messageType == JavacRemoteProto.Message.Type.REQUEST) {
+ final JavacRemoteProto.Message.Request request = msg.getRequest();
+ final JavacRemoteProto.Message.Request.Type requestType = request.getRequestType();
+ if (requestType == JavacRemoteProto.Message.Request.Type.COMPILE) {
+ final List<String> options = request.getOptionList();
+ final List<File> files = toFiles(request.getFileList());
+ final List<File> cp = toFiles(request.getClasspathList());
+ final List<File> platformCp = toFiles(request.getPlatformClasspathList());
+ final List<File> srcPath = toFiles(request.getSourcepathList());
+
+ final Map<File, Set<File>> outs = new HashMap<File, Set<File>>();
+ for (JavacRemoteProto.Message.Request.OutputGroup outputGroup : request.getOutputList()) {
+ final Set<File> srcRoots = new HashSet<File>();
+ for (String root : outputGroup.getSourceRootList()) {
+ srcRoots.add(new File(root));
+ }
+ outs.put(new File(outputGroup.getOutputRoot()), srcRoots);
+ }
+
+ final CancelHandler cancelHandler = new CancelHandler();
+ myCancelHandlers.add(cancelHandler);
+ SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
+ public void run() {
+ try {
+ final JavacRemoteProto.Message exitMsg =
+ compile(ctx, sessionId, options, files, cp, platformCp, srcPath, outs, cancelHandler);
+ Channels.write(ctx.getChannel(), exitMsg);
+ }
+ finally {
+ myCancelHandlers.remove(cancelHandler);
+ }
+ }
+ });
+ }
+ else if (requestType == JavacRemoteProto.Message.Request.Type.CANCEL){
+ cancelBuilds();
+ reply = JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createRequestAckResponse());
+ }
+ else if (requestType == JavacRemoteProto.Message.Request.Type.SHUTDOWN){
+ cancelBuilds();
+ new Thread("StopThread") {
+ public void run() {
+ try {
+ JavacServer.this.stop();
+ }
+ finally {
+ System.exit(0);
+ }
+ }
+ }.start();
+ }
+ else {
+ reply = JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createFailure("Unsupported request type: " + requestType.name(), null));
+ }
+ }
+ else {
+ reply = JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createFailure("Unsupported message: " + messageType.name(), null));
+ }
+ }
+ finally {
+ if (reply != null) {
+ Channels.write(ctx.getChannel(), reply);
+ }
+ }
+ }
+
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+ super.exceptionCaught(ctx, e);
+ }
+ }
+
+ private class ChannelRegistrar extends SimpleChannelUpstreamHandler {
+ public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ myAllOpenChannels.add(e.getChannel());
+ super.channelOpen(ctx, e);
+ }
+ }
+
+ private static class CancelHandler implements CanceledStatus {
+ private volatile boolean myIsCanceled = false;
+
+ private CancelHandler() {
+ }
+
+ public void cancel() {
+ myIsCanceled = true;
+ }
+
+ public boolean isCanceled() {
+ return myIsCanceled;
+ }
+ }
+} \ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java
new file mode 100644
index 000000000000..05a33b5ae65a
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.intellij.execution.process.BaseOSProcessHandler;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.concurrency.Semaphore;
+import org.jetbrains.jps.cmdline.ClasspathBootstrap;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/24/12
+ */
+public class JavacServerBootstrap {
+
+ public static BaseOSProcessHandler launchJavacServer(String sdkHomePath, int heapSize, int port, File workingDir, List<String> vmOptions) throws Exception {
+ final List<String> cmdLine = new ArrayList<String>();
+ appendParam(cmdLine, getVMExecutablePath(sdkHomePath));
+ appendParam(cmdLine, "-XX:MaxPermSize=150m");
+ //appendParam(cmdLine, "-XX:ReservedCodeCacheSize=64m");
+ appendParam(cmdLine, "-Djava.awt.headless=true");
+ final int xms = heapSize / 2;
+ if (xms > 32) {
+ appendParam(cmdLine, "-Xms" + xms + "m");
+ }
+ appendParam(cmdLine, "-Xmx" + heapSize + "m");
+
+ // debugging
+ //appendParam(cmdLine, "-XX:+HeapDumpOnOutOfMemoryError");
+ //appendParam(cmdLine, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5009");
+
+ // javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language
+ final String encoding = System.getProperty("file.encoding");
+ if (encoding != null) {
+ appendParam(cmdLine, "-Dfile.encoding=" + encoding);
+ }
+ final String lang = System.getProperty("user.language");
+ if (lang != null) {
+ //noinspection HardCodedStringLiteral
+ appendParam(cmdLine, "-Duser.language=" + lang);
+ }
+ final String country = System.getProperty("user.country");
+ if (country != null) {
+ //noinspection HardCodedStringLiteral
+ appendParam(cmdLine, "-Duser.country=" + country);
+ }
+ //noinspection HardCodedStringLiteral
+ final String region = System.getProperty("user.region");
+ if (region != null) {
+ //noinspection HardCodedStringLiteral
+ appendParam(cmdLine, "-Duser.region=" + region);
+ }
+
+ for (String option : vmOptions) {
+ appendParam(cmdLine, option);
+ }
+
+ appendParam(cmdLine, "-classpath");
+
+ final List<File> cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath);
+ final StringBuilder classpath = new StringBuilder();
+ for (File file : cp) {
+ if (classpath.length() > 0) {
+ classpath.append(File.pathSeparator);
+ }
+ classpath.append(file.getPath());
+ }
+ appendParam(cmdLine, classpath.toString());
+
+ appendParam(cmdLine, org.jetbrains.jps.javac.JavacServer.class.getName());
+ appendParam(cmdLine, Integer.toString(port));
+
+ workingDir.mkdirs();
+
+ appendParam(cmdLine, FileUtil.toSystemIndependentName(workingDir.getPath()));
+
+ final ProcessBuilder builder = new ProcessBuilder(cmdLine);
+ builder.directory(workingDir);
+
+ final Process process = builder.start();
+ final BaseOSProcessHandler processHandler = new BaseOSProcessHandler(process, null, null) {
+ @Override
+ protected Future<?> executeOnPooledThread(Runnable task) {
+ return SharedThreadPool.getInstance().executeOnPooledThread(task);
+ }
+ };
+ configureProcessHandler(processHandler);
+
+ return processHandler;
+ }
+
+ private static void configureProcessHandler(final BaseOSProcessHandler processHandler) throws Exception {
+ processHandler.addProcessListener(new ProcessAdapter() {
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ final String text = event.getText();
+ if (!StringUtil.isEmptyOrSpaces(text)) {
+ if (outputType == ProcessOutputTypes.STDOUT) {
+ System.out.print("JAVAC_SERVER: " + text);
+ }
+ else if (outputType == ProcessOutputTypes.STDERR){
+ System.err.print("JAVAC_SERVER: " + text);
+ }
+ }
+ }
+ });
+ final Semaphore semaphore = new Semaphore();
+ semaphore.down();
+ final Ref<String> serverStartMessage = new Ref<String>(null);
+ processHandler.addProcessListener(new ProcessAdapter() {
+ public void processTerminated(ProcessEvent event) {
+ try {
+ processHandler.removeProcessListener(this);
+ }
+ finally {
+ semaphore.up();
+ }
+ }
+
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ if (outputType == ProcessOutputTypes.STDERR) {
+ try {
+ final String text = event.getText();
+ if (text != null) {
+ if (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE)) {
+ processHandler.removeProcessListener(this);
+ serverStartMessage.set(text);
+ }
+ }
+ }
+ finally {
+ semaphore.up();
+ }
+ }
+ }
+ });
+ processHandler.startNotify();
+ semaphore.waitFor();
+
+ final String startupMsg = serverStartMessage.get();
+ if (startupMsg == null || !startupMsg.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE)) {
+ throw new Exception("Server startup failed: " + startupMsg);
+ }
+ }
+
+ private static void appendParam(List<String> cmdLine, String param) {
+ if (SystemInfo.isWindows) {
+ if (param.contains("\"")) {
+ param = StringUtil.replace(param, "\"", "\\\"");
+ }
+ else if (param.length() == 0) {
+ param = "\"\"";
+ }
+ }
+ cmdLine.add(param);
+ }
+
+ public static String getVMExecutablePath(String sdkHome) {
+ return sdkHome + "/bin/java";
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java
new file mode 100644
index 000000000000..d9103ede38b3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import org.jboss.netty.channel.MessageEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.api.RequestFuture;
+import org.jetbrains.jps.client.SimpleProtobufClient;
+import org.jetbrains.jps.client.UUIDGetter;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/22/12
+ */
+public class JavacServerClient extends SimpleProtobufClient<JavacServerResponseHandler>{
+
+ public JavacServerClient() {
+ super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.getInstance(), new UUIDGetter() {
+ @NotNull
+ public UUID getSessionUUID(@NotNull MessageEvent e) {
+ final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage();
+ final JavacRemoteProto.Message.UUID uuid = message.getSessionId();
+ return new UUID(uuid.getMostSigBits(), uuid.getLeastSigBits());
+ }
+ });
+ }
+
+ public RequestFuture<JavacServerResponseHandler> sendCompileRequest(List<String> options, Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, Map<File, Set<File>> outs, DiagnosticOutputConsumer diagnosticSink, OutputFileConsumer outputSink) {
+ final JavacServerResponseHandler rh = new JavacServerResponseHandler(diagnosticSink, outputSink);
+ final JavacRemoteProto.Message.Request request = JavacProtoUtil.createCompilationRequest(options, files, classpath, platformCp, sourcePath, outs);
+ return sendRequest(request, rh, new RequestFuture.CancelAction<JavacServerResponseHandler>() {
+ public void cancel(RequestFuture<JavacServerResponseHandler> javacServerResponseHandlerRequestFuture) throws Exception {
+ sendRequest(JavacProtoUtil.createCancelRequest(), null, null);
+ }
+ });
+ }
+
+ public RequestFuture sendShutdownRequest() {
+ return sendRequest(JavacProtoUtil.createShutdownRequest(), null, null);
+ }
+
+ private RequestFuture<JavacServerResponseHandler> sendRequest(final JavacRemoteProto.Message.Request request, final JavacServerResponseHandler responseHandler, final RequestFuture.CancelAction<JavacServerResponseHandler> cancelAction) {
+ final UUID requestId = UUID.randomUUID();
+ return sendMessage(requestId, JavacProtoUtil.toMessage(requestId, request), responseHandler, cancelAction);
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java
new file mode 100644
index 000000000000..a9d2173f29f1
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.MessageLite;
+import org.jetbrains.jps.client.ProtobufResponseHandler;
+import org.jetbrains.jps.incremental.BinaryContent;
+
+import javax.tools.*;
+import java.io.File;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Locale;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/22/12
+ */
+public class JavacServerResponseHandler implements ProtobufResponseHandler{
+ private final DiagnosticOutputConsumer myDiagnosticSink;
+ private final OutputFileConsumer myOutputSink;
+ private volatile boolean myTerminatedSuccessfully;
+
+ public JavacServerResponseHandler(DiagnosticOutputConsumer diagnosticSink, OutputFileConsumer outputSink) {
+ myDiagnosticSink = diagnosticSink;
+ myOutputSink = outputSink;
+ }
+
+ public boolean handleMessage(MessageLite message) throws Exception {
+ final JavacRemoteProto.Message msg = (JavacRemoteProto.Message)message;
+ final JavacRemoteProto.Message.Type messageType = msg.getMessageType();
+
+ if (messageType == JavacRemoteProto.Message.Type.RESPONSE) {
+ final JavacRemoteProto.Message.Response response = msg.getResponse();
+ final JavacRemoteProto.Message.Response.Type responseType = response.getResponseType();
+
+ if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE) {
+ final JavacRemoteProto.Message.Response.CompileMessage compileMessage = response.getCompileMessage();
+ final JavacRemoteProto.Message.Response.CompileMessage.Kind messageKind = compileMessage.getKind();
+
+ if (messageKind == JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT) {
+ if (compileMessage.hasText()) {
+ myDiagnosticSink.outputLineAvailable(compileMessage.getText());
+ }
+ }
+ else {
+ final String sourceUri = compileMessage.hasSourceUri()? compileMessage.getSourceUri() : null;
+ final JavaFileObject srcFileObject = sourceUri != null? new DummyJavaFileObject(URI.create(sourceUri)) : null;
+ myDiagnosticSink.report(new DummyDiagnostic(convertKind(messageKind), srcFileObject, compileMessage));
+ }
+
+ return false;
+ }
+
+ if (responseType == JavacRemoteProto.Message.Response.Type.OUTPUT_OBJECT) {
+ final JavacRemoteProto.Message.Response.OutputObject outputObject = response.getOutputObject();
+ final JavacRemoteProto.Message.Response.OutputObject.Kind kind = outputObject.getKind();
+
+ final String outputRoot = outputObject.hasOutputRoot()? outputObject.getOutputRoot() : null;
+ final File outputRootFile = outputRoot != null? new File(outputRoot) : null;
+
+ final BinaryContent fileObjectContent;
+ final ByteString content = outputObject.hasContent()? outputObject.getContent() : null;
+ if (content != null) {
+ final byte[] bytes = content.toByteArray();
+ fileObjectContent = new BinaryContent(bytes, 0, bytes.length);
+ }
+ else {
+ fileObjectContent = null;
+ }
+
+ final String sourceUri = outputObject.hasSourceUri()? outputObject.getSourceUri() : null;
+ final URI srcUri = sourceUri != null? URI.create(sourceUri) : null;
+ final OutputFileObject fileObject = new OutputFileObject(
+ null,
+ outputRootFile,
+ outputObject.hasRelativePath()? outputObject.getRelativePath() : null,
+ new File(outputObject.getFilePath()),
+ convertKind(kind),
+ outputObject.hasClassName()? outputObject.getClassName() : null,
+ srcUri,
+ fileObjectContent
+ );
+
+ myOutputSink.save(fileObject);
+ return false;
+ }
+
+ if (responseType == JavacRemoteProto.Message.Response.Type.CLASS_DATA) {
+ final JavacRemoteProto.Message.Response.ClassData data = response.getClassData();
+ final String className = data.getClassName();
+ final Collection<String> imports = data.getImportStatementList();
+ final Collection<String> staticImports = data.getStaticImportList();
+ myDiagnosticSink.registerImports(className, imports, staticImports);
+ return false;
+ }
+
+ if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED) {
+ if (response.hasCompletionStatus()) {
+ myTerminatedSuccessfully = response.getCompletionStatus();
+ }
+ return true;
+ }
+
+ if (responseType == JavacRemoteProto.Message.Response.Type.REQUEST_ACK) {
+ return true;
+ }
+
+ throw new Exception("Unsupported response type: " + responseType.name());
+ }
+
+ if (messageType == JavacRemoteProto.Message.Type.FAILURE) {
+ final JavacRemoteProto.Message.Failure failure = msg.getFailure();
+ final StringBuilder buf = new StringBuilder();
+ if (failure.hasDescription()) {
+ buf.append(failure.getDescription());
+ }
+ if (failure.hasStacktrace()) {
+ if (buf.length() > 0) {
+ buf.append("\n");
+ }
+ buf.append(failure.getStacktrace());
+ }
+ myDiagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, buf.toString()));
+ return true;
+ }
+
+ throw new Exception("Unsupported message type: " + messageType.name());
+ }
+
+ public boolean isTerminatedSuccessfully() {
+ return myTerminatedSuccessfully;
+ }
+
+ private static Diagnostic.Kind convertKind(JavacRemoteProto.Message.Response.CompileMessage.Kind kind) {
+ switch (kind) {
+ case ERROR: return Diagnostic.Kind.ERROR;
+ case WARNING: return Diagnostic.Kind.WARNING;
+ case MANDATORY_WARNING: return Diagnostic.Kind.MANDATORY_WARNING;
+ case NOTE: return Diagnostic.Kind.NOTE;
+ default : return Diagnostic.Kind.OTHER;
+ }
+ }
+
+ private static OutputFileObject.Kind convertKind(JavacRemoteProto.Message.Response.OutputObject.Kind kind) {
+ switch (kind) {
+ case CLASS: return JavaFileObject.Kind.CLASS;
+ case HTML: return JavaFileObject.Kind.HTML;
+ case SOURCE: return JavaFileObject.Kind.SOURCE;
+ default : return JavaFileObject.Kind.OTHER;
+ }
+ }
+
+ public void sessionTerminated() {
+ }
+
+ private static class DummyDiagnostic implements Diagnostic<JavaFileObject> {
+
+ private final Kind myMessageKind;
+ private final JavaFileObject mySrcFileObject;
+ private final JavacRemoteProto.Message.Response.CompileMessage myCompileMessage;
+
+ public DummyDiagnostic(final Kind messageKind, JavaFileObject srcFileObject, JavacRemoteProto.Message.Response.CompileMessage compileMessage) {
+ myMessageKind = messageKind;
+ mySrcFileObject = srcFileObject;
+ myCompileMessage = compileMessage;
+ }
+
+ public Kind getKind() {
+ return myMessageKind;
+ }
+
+ public JavaFileObject getSource() {
+ return mySrcFileObject;
+ }
+
+ public long getPosition() {
+ return myCompileMessage.hasProblemLocationOffset()? myCompileMessage.getProblemLocationOffset() : -1;
+ }
+
+ public long getStartPosition() {
+ return myCompileMessage.hasProblemBeginOffset()? myCompileMessage.getProblemBeginOffset() : -1;
+ }
+
+ public long getEndPosition() {
+ return myCompileMessage.hasProblemEndOffset()? myCompileMessage.getProblemEndOffset() : -1;
+ }
+
+ public long getLineNumber() {
+ return myCompileMessage.hasLine()? myCompileMessage.getLine() : -1;
+ }
+
+ public long getColumnNumber() {
+ return myCompileMessage.hasColumn()? myCompileMessage.getColumn() : -1;
+ }
+
+ public String getCode() {
+ return null;
+ }
+
+ public String getMessage(Locale locale) {
+ return myCompileMessage.hasText()? myCompileMessage.getText() : null;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java
new file mode 100644
index 000000000000..89c7be1cda83
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.List;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.*;
+import java.io.*;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * WARNING: Loaded via reflection, do not delete
+ *
+ * @author nik
+ * @noinspection UnusedDeclaration
+ */
+class OptimizedFileManager extends DefaultFileManager {
+ private boolean myUseZipFileIndex;
+ private final Map<File, Archive> myArchives;
+ private final Map<File, Boolean> myIsFile = new HashMap<File, Boolean>();
+ private final Map<InputFileObject, SoftReference<CharBuffer>> myContentCache = new HashMap<InputFileObject, SoftReference<CharBuffer>>();
+ private final Map<File, File[]> myDirectoryCache = new HashMap<File, File[]>();
+ public static final File[] NULL_FILE_ARRAY = new File[0];
+
+ public OptimizedFileManager() throws Throwable {
+ super(new Context(), true, null);
+ final Field archivesField = DefaultFileManager.class.getDeclaredField("archives");
+ archivesField.setAccessible(true);
+ myArchives = (Map<File, Archive>) archivesField.get(this);
+
+ try {
+ final Field useZipFileIndexField = DefaultFileManager.class.getDeclaredField("useZipFileIndex");
+ useZipFileIndexField.setAccessible(true);
+ myUseZipFileIndex = (Boolean) useZipFileIndexField.get(this);
+ }
+ catch (Exception e) {
+ myUseZipFileIndex = false;
+ }
+ }
+
+ @Override
+ public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
+ final String name = StringUtil.isEmpty(packageName) ? FileUtil.toSystemIndependentName(relativeName) : (packageName.replace('.', '/') + "/" + FileUtil.toSystemIndependentName(relativeName));
+ return getFileForInput(location, name);
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
+ final String name = className.replace('.', '/') + kind.extension;
+ return getFileForInput(location, name);
+ }
+
+ @Override
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
+ java.util.List<InputFileObject> result;
+ if (files instanceof Collection) {
+ result = new ArrayList<InputFileObject>(((Collection)files).size());
+ }
+ else {
+ result = new ArrayList<InputFileObject>();
+ }
+ for (File f: files) {
+ result.add(new InputFileObject(f));
+ }
+ return result;
+ }
+
+ @Override
+ public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
+ Iterable<? extends File> locationRoots = getLocation(location);
+ if (locationRoots == null) {
+ return Collections.emptyList();
+ }
+
+ final String relativePath = packageName.replace('.', File.separatorChar);
+ ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
+
+ for (File root : locationRoots) {
+ final Archive archive = myArchives.get(root);
+ final boolean isFile;
+ if (archive != null) {
+ isFile = true;
+ }
+ else {
+ isFile = isFile(root);
+ }
+ if (isFile) {
+ collectFromArchive(root, archive, relativePath, kinds, recurse, results);
+ }
+ else {
+ final File directory = relativePath.length() != 0 ? new File(root, relativePath) : root;
+ if (recurse) {
+ collectFromDirectoryRecursively(directory, kinds, results, true, !location.isOutputLocation());
+ }
+ else {
+ collectFromDirectory(directory, kinds, results, !location.isOutputLocation());
+ }
+ }
+ }
+
+ return results.toList();
+ }
+
+ private boolean isFile(File root) {
+ Boolean cachedIsFile = myIsFile.get(root);
+ if (cachedIsFile == null) {
+ cachedIsFile = Boolean.valueOf(root.isFile());
+ myIsFile.put(root, cachedIsFile);
+ }
+ return cachedIsFile.booleanValue();
+ }
+
+ private void collectFromArchive(File root, Archive archive, String relativePath, Set<JavaFileObject.Kind> kinds, boolean recurse, ListBuffer<JavaFileObject> result) {
+ if (archive == null) {
+ try {
+ archive = openArchive(root);
+ }
+ catch (IOException ex) {
+ log.error("error.reading.file", root, ex.getLocalizedMessage());
+ return;
+ }
+ }
+ final String separator = myUseZipFileIndex ? File.separator : "/";
+ if (relativePath.length() != 0) {
+ if (!myUseZipFileIndex) {
+ relativePath = relativePath.replace('\\', '/');
+ }
+ if (!relativePath.endsWith(separator)) {
+ relativePath = relativePath + separator;
+ }
+ }
+
+ collectArchiveFiles(archive, relativePath, kinds, result);
+ if (recurse) {
+ for (String s : archive.getSubdirectories()) {
+ if (s.startsWith(relativePath) && !s.equals(relativePath)) {
+ if (!s.endsWith(separator)) {
+ s += separator;
+ }
+ collectArchiveFiles(archive, s, kinds, result);
+ }
+ }
+ }
+ }
+
+ private void collectFromDirectory(File directory, Set<JavaFileObject.Kind> fileKinds, ListBuffer<JavaFileObject> result, boolean canUseCache) {
+ final File[] children = listChildren(directory, canUseCache);
+ if (children != null) {
+ final boolean acceptUnknownFiles = fileKinds.contains(JavaFileObject.Kind.OTHER);
+ for (File child : children) {
+ if (isValidFile(child.getName(), fileKinds)) {
+ if (acceptUnknownFiles && !isFile(child)) {
+ continue;
+ }
+ final JavaFileObject fe = new InputFileObject(child);
+ result.append(fe);
+ }
+ }
+ }
+ }
+
+ private void collectFromDirectoryRecursively(File file, Set<JavaFileObject.Kind> fileKinds, ListBuffer<JavaFileObject> result, boolean isRootCall, boolean canUseCache) {
+ final File[] children = listChildren(file, canUseCache);
+ final String name = file.getName();
+ if (children != null) { // is directory
+ if (isRootCall || SourceVersion.isIdentifier(name)) {
+ for (File child : children) {
+ collectFromDirectoryRecursively(child, fileKinds, result, false, canUseCache);
+ }
+ }
+ }
+ else {
+ if (isValidFile(name, fileKinds)) {
+ JavaFileObject fe = new InputFileObject(file);
+ result.append(fe);
+ }
+ }
+ }
+
+ private File[] listChildren(File file, boolean canUseCache) {
+ if (!canUseCache) {
+ return file.listFiles();
+ }
+ File[] cached = myDirectoryCache.get(file);
+ if (cached == null) {
+ cached = file.listFiles();
+ myDirectoryCache.put(file, cached != null? cached : NULL_FILE_ARRAY);
+ }
+ return cached == NULL_FILE_ARRAY ? null : cached;
+ }
+
+ private void collectArchiveFiles(Archive archive, String relativePath, Set<JavaFileObject.Kind> fileKinds, ListBuffer<JavaFileObject> result) {
+ List<String> files = archive.getFiles(relativePath);
+ if (files != null) {
+ for (String file; !files.isEmpty(); files = files.tail) {
+ file = files.head;
+ if (isValidFile(file, fileKinds)) {
+ result.append(archive.getFileObject(relativePath, file));
+ }
+ }
+ }
+ }
+
+ private boolean isValidFile(String name, Set<JavaFileObject.Kind> fileKinds) {
+ int dot = name.lastIndexOf(".");
+ JavaFileObject.Kind kind = getKind(dot == -1 ? name : name.substring(dot));
+ return fileKinds.contains(kind);
+ }
+
+ private JavaFileObject getFileForInput(Location location, String name) throws IOException {
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null) {
+ return null;
+ }
+
+ for (File root : path) {
+ Archive archive = myArchives.get(root);
+ final boolean isFile;
+ if (archive != null) {
+ isFile = true;
+ }
+ else {
+ isFile = isFile(root);
+ }
+ if (isFile) {
+ if (archive == null) {
+ try {
+ archive = openArchive(root);
+ }
+ catch (IOException ex) {
+ log.error("error.reading.file", root, ex.getLocalizedMessage());
+ break;
+ }
+ }
+ if (archive.contains(name)) {
+ int i = name.lastIndexOf('/');
+ String dirname = name.substring(0, i+1);
+ String basename = name.substring(i+1);
+ return archive.getFileObject(dirname, basename);
+ }
+ }
+ else {
+ final File f = new File(root, name.replace('/', File.separatorChar));
+ if (f.exists()) {
+ return new InputFileObject(f);
+ }
+ }
+ }
+ return null;
+ }
+
+ //actually Javac doesn't check if this method returns null. It always get substring of the returned string starting from the last dot.
+ @Override
+ public String inferBinaryName(Location location, JavaFileObject file) {
+ final String name = file.getName();
+ int dot = name.lastIndexOf('.');
+ final String relativePath = dot != -1 ? name.substring(0, dot) : name;
+ return relativePath.replace(File.separatorChar, '.');
+ }
+
+ private class InputFileObject extends BaseFileObject {
+
+ /** The underlying file.
+ */
+ final File f;
+
+ public InputFileObject(File f) {
+ this.f = f;
+ }
+
+ public InputStream openInputStream() throws IOException {
+ return new FileInputStream(f);
+ }
+
+ public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public String getName() {
+ return f.getPath();
+ }
+
+ public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
+ final String n = simpleName + kind.extension;
+ final String fileName = f.getName();
+ if (fileName.equals(n)) {
+ return true;
+ }
+ if (fileName.equalsIgnoreCase(n)) {
+ try {
+ // allow for Windows
+ return (f.getCanonicalFile().getName().equals(n));
+ }
+ catch (IOException e) {
+ }
+ }
+ return false;
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getPath() {
+ return f.getPath();
+ }
+
+ public long getLastModified() {
+ return f.lastModified();
+ }
+
+ public boolean delete() {
+ return f.delete();
+ }
+
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ SoftReference<CharBuffer> r = myContentCache.get(this);
+ CharBuffer cb = (r == null ? null : r.get());
+ if (cb == null) {
+ InputStream in = new FileInputStream(f);
+ try {
+ final ByteBuffer bb = makeByteBuffer(in);
+ JavaFileObject prev = log.useSource(this);
+ try {
+ cb = decode(bb, ignoreEncodingErrors);
+ }
+ finally {
+ log.useSource(prev);
+ }
+ myByteBufferCache.put(bb); // save for next time
+ if (!ignoreEncodingErrors) {
+ myContentCache.put(this, new SoftReference<CharBuffer>(cb));
+ }
+ }
+ finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ //public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ // final String encodingName = getEncodingName();
+ // SoftReference<CharBuffer> r = myContentCache.get(this);
+ // CharBuffer cb = (r == null ? null : r.get());
+ // if (cb == null) {
+ // InputStream in = new FileInputStream(f);
+ // try {
+ // JavaFileObject prev = log.useSource(this);
+ // try {
+ // final char[] chars = FileUtil.loadFileText(f, encodingName);
+ // cb = CharBuffer.wrap(chars);
+ // }
+ // finally {
+ // log.useSource(prev);
+ // }
+ // if (!ignoreEncodingErrors) {
+ // myContentCache.put(this, new SoftReference<CharBuffer>(cb));
+ // }
+ // }
+ // finally {
+ // in.close();
+ // }
+ // }
+ // return cb;
+ //}
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof InputFileObject)) {
+ return false;
+ }
+ InputFileObject o = (InputFileObject) other;
+ try {
+ return f.equals(o.f) || f.getCanonicalFile().equals(o.f.getCanonicalFile());
+ }
+ catch (IOException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return f.hashCode();
+ }
+
+ public URI toUri() {
+ try {
+ return new URI(f.getPath());
+ }
+ catch (URISyntaxException ex) {
+ return f.toURI();
+ }
+ }
+ }
+
+ private ByteBuffer makeByteBuffer(InputStream in) throws IOException {
+ int limit = in.available();
+ if (limit < 1024) {
+ limit = 1024;
+ }
+ ByteBuffer result = myByteBufferCache.get(limit);
+ int position = 0;
+ while (in.available() != 0) {
+ if (position >= limit) {
+ // expand buffer
+ result = ByteBuffer.allocate(limit <<= 1).put((ByteBuffer)result.flip());
+ }
+ final int count = in.read(result.array(), position, limit - position);
+ if (count < 0) {
+ break;
+ }
+ result.position(position += count);
+ }
+ return (ByteBuffer)result.flip();
+ }
+
+ private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
+ CharsetDecoder decoder;
+ String encodingName = getEncodingName();
+ try {
+ Charset charset = (this.charset == null) ? Charset.forName(encodingName) : this.charset;
+ decoder = charset.newDecoder();
+
+ CodingErrorAction action;
+ if (ignoreEncodingErrors) {
+ action = CodingErrorAction.REPLACE;
+ }
+ else {
+ action = CodingErrorAction.REPORT;
+ }
+
+ decoder.onMalformedInput(action).onUnmappableCharacter(action);
+ }
+ catch (IllegalCharsetNameException e) {
+ log.error("unsupported.encoding", encodingName);
+ return (CharBuffer)CharBuffer.allocate(1).flip();
+ }
+ catch (UnsupportedCharsetException e) {
+ log.error("unsupported.encoding", encodingName);
+ return (CharBuffer)CharBuffer.allocate(1).flip();
+ }
+
+ // slightly overestimate the buffer size to avoid reallocation.
+ final float factor = decoder.averageCharsPerByte() * 0.8f + decoder.maxCharsPerByte() * 0.2f;
+ CharBuffer dest = CharBuffer.allocate(10 + (int)(inbuf.remaining() * factor));
+
+ while (true) {
+ CoderResult result = decoder.decode(inbuf, dest, true);
+ dest.flip();
+
+ if (result.isUnderflow()) { // done reading
+ // make sure there is at least one extra character
+ if (dest.limit() == dest.capacity()) {
+ dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
+ dest.flip();
+ }
+ return dest;
+ }
+ else if (result.isOverflow()) { // buffer too small; expand
+ int newCapacity = 10 + dest.capacity() + (int)(inbuf.remaining()*decoder.maxCharsPerByte());
+ dest = CharBuffer.allocate(newCapacity).put(dest);
+ }
+ else if (result.isMalformed() || result.isUnmappable()) {
+ // bad character in input
+
+ // report coding error (warn only pre 1.5)
+ if (!getSource().allowEncodingErrors()) {
+ log.error(new JCDiagnostic.SimpleDiagnosticPosition(dest.limit()), "illegal.char.for.encoding", charset == null ? encodingName : charset.name());
+ }
+ else {
+ log.warning(new JCDiagnostic.SimpleDiagnosticPosition(dest.limit()), "illegal.char.for.encoding", charset == null ? encodingName : charset.name());
+ }
+
+ // skip past the coding error
+ inbuf.position(inbuf.position() + result.length());
+
+ // undo the flip() to prepare the output buffer
+ // for more translation
+ dest.position(dest.limit());
+ dest.limit(dest.capacity());
+ dest.put((char)0xfffd); // backward compatible
+ }
+ else {
+ throw new AssertionError(result);
+ }
+ }
+ // unreached
+ }
+
+ private static class ByteBufferCache {
+ private AtomicReference<ByteBuffer> myCached = new AtomicReference<ByteBuffer>(null);
+
+ ByteBuffer get(int capacity) {
+ if (capacity < 20480) {
+ capacity = 20480;
+ }
+ final ByteBuffer cached = myCached.getAndSet(null);
+ return (cached != null && cached.capacity() >= capacity) ? (ByteBuffer)cached.clear() : ByteBuffer.allocate(capacity + capacity>>1);
+ }
+
+ void put(ByteBuffer x) {
+ myCached.set(x);
+ }
+ }
+ private final ByteBufferCache myByteBufferCache = new ByteBufferCache();
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java
new file mode 100644
index 000000000000..80f06fd182c0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.file.RelativePath;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.*;
+import java.io.*;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.util.*;
+
+/**
+ * WARNING: Loaded via reflection, do not delete
+ *
+ * @noinspection UnusedDeclaration
+ */
+class OptimizedFileManager17 extends com.sun.tools.javac.file.JavacFileManager {
+ private boolean myUseZipFileIndex;
+ private final Map<File, Archive> myArchives;
+ private final Map<File, Boolean> myIsFile = new HashMap<File, Boolean>();
+ private final Map<File, File[]> myDirectoryCache = new HashMap<File, File[]>();
+ public static final File[] NULL_FILE_ARRAY = new File[0];
+
+ public OptimizedFileManager17() throws Throwable {
+ super(new Context(), true, null);
+ final Field archivesField = com.sun.tools.javac.file.JavacFileManager.class.getDeclaredField("archives");
+ archivesField.setAccessible(true);
+ myArchives = (Map<File, Archive>) archivesField.get(this);
+ }
+
+ @Override
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
+ java.util.List<InputFileObject> result;
+ if (files instanceof Collection) {
+ result = new ArrayList<InputFileObject>(((Collection)files).size());
+ }
+ else {
+ result = new ArrayList<InputFileObject>();
+ }
+ for (File f: files) {
+ result.add(new InputFileObject(this, f));
+ }
+ return result;
+ }
+
+ @Override
+ public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
+ Iterable<? extends File> locationRoots = getLocation(location);
+ if (locationRoots == null) {
+ return List.nil();
+ }
+
+ RelativePath.RelativeDirectory subdirectory = new RelativePath.RelativeDirectory(packageName.replace('.', '/'));
+
+ ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
+
+ for (File root : locationRoots) {
+ Archive archive = myArchives.get(root);
+
+ final boolean isFile;
+ if (archive != null) {
+ isFile = true;
+ }
+ else {
+ isFile = isFile(root);
+ }
+
+ if (isFile) {
+ // Not a directory; either a file or non-existant, create the archive
+ try {
+ if (archive == null) {
+ archive = openArchive(root);
+ }
+ listArchive(archive, subdirectory, kinds, recurse, results);
+ }
+ catch (IOException ex) {
+ log.error("error.reading.file", root, getMessage(ex));
+ }
+ }
+ else {
+ final File dir = subdirectory.getFile(root);
+ if (recurse) {
+ listDirectoryRecursively(dir, kinds, results, true, !location.isOutputLocation());
+ }
+ else {
+ listDirectory(dir, kinds, results, !location.isOutputLocation());
+ }
+ }
+
+ }
+ return results.toList();
+ }
+
+ private static void listArchive(Archive archive, RelativePath.RelativeDirectory subdirectory, Set<JavaFileObject.Kind> fileKinds, boolean recurse, ListBuffer<JavaFileObject> resultList) {
+ // Get the files directly in the subdir
+ List<String> files = archive.getFiles(subdirectory);
+ if (files != null) {
+ for (; !files.isEmpty(); files = files.tail) {
+ String file = files.head;
+ if (isValidFile(file, fileKinds)) {
+ resultList.append(archive.getFileObject(subdirectory, file));
+ }
+ }
+ }
+ if (recurse) {
+ for (RelativePath.RelativeDirectory s: archive.getSubdirectories()) {
+ if (contains(subdirectory, s)) {
+ // Because the archive map is a flat list of directories,
+ // the enclosing loop will pick up all child subdirectories.
+ // Therefore, there is no need to recurse deeper.
+ listArchive(archive, s, fileKinds, false, resultList);
+ }
+ }
+ }
+ }
+
+ private void listDirectory(File directory, Set<JavaFileObject.Kind> fileKinds, ListBuffer<JavaFileObject> resultList, boolean canUseCache) {
+ final File[] files = listChildren(directory, canUseCache);
+ if (files != null) {
+ if (sortFiles != null) {
+ Arrays.sort(files, sortFiles);
+ }
+ final boolean acceptUnknownFiles = fileKinds.contains(JavaFileObject.Kind.OTHER);
+ for (File f: files) {
+ final String fileName = f.getName();
+ if (isValidFile(fileName, fileKinds)) {
+ if (acceptUnknownFiles && !isFile(f)) {
+ continue;
+ }
+ final JavaFileObject fe = new InputFileObject(this, f);
+ resultList.append(fe);
+ }
+ }
+ }
+ }
+
+ private void listDirectoryRecursively(File file, Set<JavaFileObject.Kind> fileKinds, ListBuffer<JavaFileObject> resultList, boolean isRootCall, boolean canUseCache) {
+ final File[] children = listChildren(file, canUseCache);
+ final String fileName = file.getName();
+ if (children != null) { // is directory
+ if (isRootCall || SourceVersion.isIdentifier(fileName)) {
+ if (sortFiles != null) {
+ Arrays.sort(children, sortFiles);
+ }
+ for (File child : children) {
+ listDirectoryRecursively(child, fileKinds, resultList, false, canUseCache);
+ }
+ }
+ }
+ else {
+ if (isValidFile(fileName, fileKinds)) {
+ JavaFileObject fe = new InputFileObject(this, file);
+ resultList.append(fe);
+ }
+ }
+ }
+
+ private File[] listChildren(File file, boolean canUseCache) {
+ if (!canUseCache) {
+ return file.listFiles();
+ }
+ File[] cached = myDirectoryCache.get(file);
+ if (cached == null) {
+ cached = file.listFiles();
+ myDirectoryCache.put(file, cached != null? cached : NULL_FILE_ARRAY);
+ }
+ return cached == NULL_FILE_ARRAY ? null : cached;
+ }
+
+ private boolean isFile(File root) {
+ Boolean cachedIsFile = myIsFile.get(root);
+ if (cachedIsFile == null) {
+ cachedIsFile = Boolean.valueOf(root.isFile());
+ myIsFile.put(root, cachedIsFile);
+ }
+ return cachedIsFile.booleanValue();
+ }
+
+ private static boolean contains(RelativePath.RelativeDirectory subdirectory, RelativePath.RelativeDirectory other) {
+ final String subdirPath = subdirectory.getPath();
+ final String otherPath = other.getPath();
+ return otherPath.length() > subdirPath.length() && otherPath.startsWith(subdirPath);
+ }
+
+ private static boolean isValidFile(String name, Set<JavaFileObject.Kind> fileKinds) {
+ return fileKinds.contains(getKind(name));
+ }
+
+ private class InputFileObject extends BaseFileObject {
+ private String name;
+ final File file;
+ private Reference<File> absFileRef;
+
+ public InputFileObject(JavacFileManager fileManager, File f) {
+ this(fileManager, f.getName(), f);
+ }
+
+ public InputFileObject(JavacFileManager fileManager, String name, File f) {
+ super(fileManager);
+ this.name = name;
+ this.file = f;
+ }
+
+
+ @Override
+ public URI toUri() {
+ return file.toURI().normalize();
+ }
+
+ @Override
+ public String getName() {
+ return file.getPath();
+ }
+
+ @Override
+ public String getShortName() {
+ return name;
+ }
+
+ @Override
+ public JavaFileObject.Kind getKind() {
+ return getKind(name);
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getLastModified() {
+ return file.lastModified();
+ }
+
+ @Override
+ public boolean delete() {
+ return file.delete();
+ }
+
+ @Override
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+ }
+
+ @Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ String fPath = file.getPath();
+ //System.err.println("RegularFileObject " + file + " " +r.getPath());
+ for (File dir: path) {
+ //System.err.println("dir: " + dir);
+ String dPath = dir.getPath();
+ if (dPath.length() == 0)
+ dPath = System.getProperty("user.dir");
+ if (!dPath.endsWith(File.separator))
+ dPath += File.separator;
+ if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
+ && new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) {
+ String relativeName = fPath.substring(dPath.length());
+ return removeExtension(relativeName).replace(File.separatorChar, '.');
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
+ cn.getClass();
+ // null check
+ if (kind == Kind.OTHER && getKind() != kind) {
+ return false;
+ }
+ String n = cn + kind.extension;
+ if (name.equals(n)) {
+ return true;
+ }
+ if (name.equalsIgnoreCase(n)) {
+ return file.getName().equals(n);
+ }
+ return false;
+ }
+
+ /**
+ * Check if two file objects are equal.
+ * Two RegularFileObjects are equal if the absolute paths of the underlying
+ * files are equal.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
+ if (!(other instanceof InputFileObject))
+ return false;
+
+ InputFileObject o = (InputFileObject) other;
+ return getAbsoluteFile().equals(o.getAbsoluteFile());
+ }
+
+ @Override
+ public int hashCode() {
+ return getAbsoluteFile().hashCode();
+ }
+
+ private File getAbsoluteFile() {
+ File absFile = (absFileRef == null ? null : absFileRef.get());
+ if (absFile == null) {
+ absFile = file.getAbsoluteFile();
+ absFileRef = new SoftReference<File>(absFile);
+ }
+ return absFile;
+ }
+
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ CharBuffer cb = fileManager.getCachedContent(this);
+ if (cb == null) {
+ InputStream in = new FileInputStream(file);
+ try {
+ ByteBuffer bb = fileManager.makeByteBuffer(in);
+ JavaFileObject prev = fileManager.log.useSource(this);
+ try {
+ cb = fileManager.decode(bb, ignoreEncodingErrors);
+ } finally {
+ fileManager.log.useSource(prev);
+ }
+ fileManager.recycleByteBuffer(bb);
+ if (!ignoreEncodingErrors) {
+ fileManager.cache(this, cb);
+ }
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+ }
+
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileConsumer.java
new file mode 100644
index 000000000000..c0835f801e90
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileConsumer.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 1/22/12
+*/
+public interface OutputFileConsumer {
+ void save(@NotNull OutputFileObject fileObject);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileObject.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileObject.java
new file mode 100644
index 000000000000..ae4c6f97677d
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OutputFileObject.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.incremental.BinaryContent;
+import org.jetbrains.jps.incremental.Utils;
+
+import javax.tools.*;
+import java.io.*;
+import java.net.URI;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/24/11
+ */
+public final class OutputFileObject extends SimpleJavaFileObject {
+ @Nullable
+ private final JavacFileManager.Context myContext;
+ @Nullable
+ private final File myOutputRoot;
+ private final String myRelativePath;
+ private final File myFile;
+ @Nullable
+ private final String myClassName;
+ @Nullable private final URI mySourceUri;
+ private volatile BinaryContent myContent;
+ private final File mySourceFile;
+
+ public OutputFileObject(@NotNull JavacFileManager.Context context, @Nullable File outputRoot, String relativePath, @NotNull File file, @NotNull Kind kind, @Nullable String className, @Nullable final URI sourceUri) {
+ this(context, outputRoot, relativePath, file, kind, className, sourceUri, null);
+ }
+
+ public OutputFileObject(@Nullable JavacFileManager.Context context, @Nullable File outputRoot, String relativePath, @NotNull File file, @NotNull Kind kind, @Nullable String className, @Nullable final URI srcUri, @Nullable BinaryContent content) {
+ super(Utils.toURI(file.getPath()), kind);
+ myContext = context;
+ mySourceUri = srcUri;
+ myContent = content;
+ myOutputRoot = outputRoot;
+ myRelativePath = relativePath;
+ myFile = file;
+ myClassName = className != null? className.replace('/', '.') : null;
+ mySourceFile = srcUri != null? Utils.convertToFile(srcUri) : null;
+ }
+
+ @Nullable
+ public File getOutputRoot() {
+ return myOutputRoot;
+ }
+
+ public String getRelativePath() {
+ return myRelativePath;
+ }
+
+ @NotNull
+ public File getFile() {
+ return myFile;
+ }
+
+ @Nullable
+ public String getClassName() {
+ return myClassName;
+ }
+
+ @Nullable
+ public File getSourceFile() {
+ return mySourceFile;
+ }
+
+ @Nullable
+ public URI getSourceUri() {
+ return mySourceUri;
+ }
+
+ @Override
+ public ByteArrayOutputStream openOutputStream() {
+ return new ByteArrayOutputStream() {
+ @Override
+ public void close() throws IOException {
+ try {
+ super.close();
+ }
+ finally {
+ myContent = new BinaryContent(buf, 0, size());
+ if (myContext != null) {
+ myContext.consumeOutputFile(OutputFileObject.this);
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ final BinaryContent bytes = myContent;
+ if (bytes != null) {
+ return new ByteArrayInputStream(bytes.getBuffer(), bytes.getOffset(), bytes.getLength());
+ }
+ return new BufferedInputStream(new FileInputStream(myFile));
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ final BinaryContent content = myContent;
+ if (content == null) {
+ throw new FileNotFoundException(toUri().getPath());
+ }
+ return new String(content.getBuffer(), content.getOffset(), content.getLength());
+ }
+
+ @Nullable
+ public BinaryContent getContent() {
+ return myContent;
+ }
+
+ public void updateContent(@NotNull byte[] updatedContent) {
+ myContent = new BinaryContent(updatedContent, 0, updatedContent.length);
+ }
+
+ @Override
+ public int hashCode() {
+ return toUri().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof JavaFileObject && toUri().equals(((JavaFileObject)obj).toUri());
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/PlainMessageDiagnostic.java b/jps/jps-builders/src/org/jetbrains/jps/javac/PlainMessageDiagnostic.java
new file mode 100644
index 000000000000..2cfde0e9c307
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/PlainMessageDiagnostic.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.javac;
+
+import javax.tools.*;
+import java.util.Locale;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/24/11
+ */
+public final class PlainMessageDiagnostic implements Diagnostic<JavaFileObject>{
+
+ private final Kind myKind;
+ private final String myMessage;
+
+ public PlainMessageDiagnostic(Kind kind, String message) {
+ myKind = kind;
+ myMessage = message;
+ }
+
+ public Kind getKind() {
+ return myKind;
+ }
+
+ public JavaFileObject getSource() {
+ return null;
+ }
+
+ public long getPosition() {
+ return 0;
+ }
+
+ public long getStartPosition() {
+ return 0;
+ }
+
+ public long getEndPosition() {
+ return 0;
+ }
+
+ public long getLineNumber() {
+ return 0;
+ }
+
+ public long getColumnNumber() {
+ return 0;
+ }
+
+ public String getCode() {
+ return null;
+ }
+
+ public String getMessage(Locale locale) {
+ return myMessage;
+ }
+}
diff --git a/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/a.txt b/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/a.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/a.txt
diff --git a/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/artifactIncludesArchiveArtifact.ipr b/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/artifactIncludesArchiveArtifact.ipr
new file mode 100644
index 000000000000..8853c2dae7c1
--- /dev/null
+++ b/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/artifactIncludesArchiveArtifact.ipr
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact type="jar" name="a">
+ <output-path>$PROJECT_DIR$/data</output-path>
+ <root id="archive" name="a.jar">
+ <element id="file-copy" path="$PROJECT_DIR$/a.txt" />
+ </root>
+ </artifact>
+ <artifact name="data">
+ <output-path>$ARTIFACTS_OUT$/data</output-path>
+ <root id="root">
+ <element id="artifact" artifact-name="a" />
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules />
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.iml b/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.ipr b/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.ipr
new file mode 100644
index 000000000000..c05b3c3683aa
--- /dev/null
+++ b/jps/jps-builders/testData/output/artifactWithoutOutput/artifactWithoutOutput.ipr
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="data:">
+ <root id="root">
+ <element id="file-copy" path="$PROJECT_DIR$/data.txt" />
+ </root>
+ </artifact>
+ <artifact name="data;">
+ <root id="root">
+ <element id="file-copy" path="$PROJECT_DIR$/data.txt" output-file-name="data2.txt"/>
+ </root>
+ </artifact>
+ <artifact name="main">
+ <output-path>$OUTPUT_DIR$/artifacts/main</output-path>
+ <root id="root">
+ <element id="artifact" artifact-name="data:" />
+ <element id="artifact" artifact-name="data;" />
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/artifactWithoutOutput.iml" filepath="$PROJECT_DIR$/artifactWithoutOutput.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/artifactWithoutOutput/data.txt b/jps/jps-builders/testData/output/artifactWithoutOutput/data.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/artifactWithoutOutput/data.txt
diff --git a/jps/jps-builders/testData/output/extractDirTest/extractDirTest.ipr b/jps/jps-builders/testData/output/extractDirTest/extractDirTest.ipr
new file mode 100644
index 000000000000..f75d2fac0540
--- /dev/null
+++ b/jps/jps-builders/testData/output/extractDirTest/extractDirTest.ipr
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="extractRoot">
+ <output-path>$ARTIFACTS_OUT$/extractRoot</output-path>
+ <root id="root">
+ <element id="directory" name="extracted">
+ <element id="extracted-dir" path="$PROJECT_DIR$/lib/a.jar" path-in-jar="/" />
+ </element>
+ </root>
+ </artifact>
+ <artifact name="extractDir">
+ <output-path>$ARTIFACTS_OUT$/extractDir</output-path>
+ <root id="root">
+ <element id="extracted-dir" path="$PROJECT_DIR$/lib/a.jar" path-in-jar="/dir/" />
+ </root>
+ </artifact>
+ <artifact type="jar" name="packedRoot">
+ <output-path>$ARTIFACTS_OUT$/packedRoot</output-path>
+ <root id="archive" name="packedRoot.jar">
+ <element id="extracted-dir" path="$PROJECT_DIR$/lib/a.jar" path-in-jar="/" />
+ </root>
+ </artifact>
+ <artifact type="jar" name="packedDir">
+ <output-path>$ARTIFACTS_OUT$/packedDir</output-path>
+ <root id="archive" name="packedDir.jar">
+ <element id="extracted-dir" path="$PROJECT_DIR$/lib/a.jar" path-in-jar="/dir/" />
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/extractDirTest/lib/a.jar b/jps/jps-builders/testData/output/extractDirTest/lib/a.jar
new file mode 100644
index 000000000000..5c9607f4ec0c
--- /dev/null
+++ b/jps/jps-builders/testData/output/extractDirTest/lib/a.jar
Binary files differ
diff --git a/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.iml b/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.ipr b/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.ipr
new file mode 100644
index 000000000000..fa9ba1cbda1b
--- /dev/null
+++ b/jps/jps-builders/testData/output/javacFileEncoding/javacFileEncoding.ipr
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ </component>
+ <component name="ClearCaseSharedConfig">
+ <option name="myUseUcmModel" value="true" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing enabled="false" useClasspath="true" />
+ </component>
+ <component name="CopyrightManager" default="">
+ <module2copyright />
+ </component>
+ <component name="DependencyValidationManager">
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </component>
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
+ <file url="PROJECT" charset="UTF-8" />
+ </component>
+ <component name="EntryPointsManager">
+ <entry_points version="2.0" />
+ </component>
+ <component name="IdProvider" IDEtalkID="57BC5002D233796DA404A8C8F3EE50DB" />
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="NullableNotNullManager">
+ <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+ <option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
+ <option name="myNullables">
+ <value>
+ <list size="0" />
+ </value>
+ </option>
+ <option name="myNotNulls">
+ <value>
+ <list size="3">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+ </list>
+ </value>
+ </option>
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/javacFileEncoding.iml" filepath="$PROJECT_DIR$/javacFileEncoding.iml" />
+ </modules>
+ </component>
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/javacFileEncoding/src/MyClass.java b/jps/jps-builders/testData/output/javacFileEncoding/src/MyClass.java
new file mode 100644
index 000000000000..1682ee345684
--- /dev/null
+++ b/jps/jps-builders/testData/output/javacFileEncoding/src/MyClass.java
@@ -0,0 +1,11 @@
+/**
+ * Created by IntelliJ IDEA.
+ * User: nik
+ * Date: 4/5/11
+ * Time: 4:39 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MyClass {
+ /* тут что-то написано по-русски в кодировке UTF8 */
+ private final static int MY_CONST = 1;
+}
diff --git a/jps/jps-builders/testData/output/manifestInArtifact/META-INF/MANIFEST.MF b/jps/jps-builders/testData/output/manifestInArtifact/META-INF/MANIFEST.MF
new file mode 100644
index 000000000000..2706814bd46f
--- /dev/null
+++ b/jps/jps-builders/testData/output/manifestInArtifact/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: MyClass
+
diff --git a/jps/jps-builders/testData/output/manifestInArtifact/manifest.ipr b/jps/jps-builders/testData/output/manifestInArtifact/manifest.ipr
new file mode 100644
index 000000000000..a83e44ac8c18
--- /dev/null
+++ b/jps/jps-builders/testData/output/manifestInArtifact/manifest.ipr
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact type="jar" name="simple">
+ <output-path>$ARTIFACTS_OUT$/simple</output-path>
+ <root id="archive" name="simple.jar">
+ <element id="directory" name="META-INF">
+ <element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
+ </element>
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/moduleClasspath/main/lib/service.jar b/jps/jps-builders/testData/output/moduleClasspath/main/lib/service.jar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/main/lib/service.jar
diff --git a/jps/jps-builders/testData/output/moduleClasspath/main/main.iml b/jps/jps-builders/testData/output/moduleClasspath/main/main.iml
new file mode 100644
index 000000000000..f955c0501a1f
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/main/main.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="module" module-name="test-util" scope="TEST" />
+ <orderEntry type="module-library">
+ <library name="service">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/service.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleClasspath/moduleClasspath.ipr b/jps/jps-builders/testData/output/moduleClasspath/moduleClasspath.ipr
new file mode 100644
index 000000000000..be6eab93eab0
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/moduleClasspath.ipr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/main/main.iml" filepath="$PROJECT_DIR$/main/main.iml" />
+ <module fileurl="file://$PROJECT_DIR$/test-util/test-util.iml" filepath="$PROJECT_DIR$/test-util/test-util.iml" />
+ <module fileurl="file://$PROJECT_DIR$/util/util.iml" filepath="$PROJECT_DIR$/util/util.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/provided.jar b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/provided.jar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/provided.jar
diff --git a/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/runtime.jar b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/runtime.jar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/runtime.jar
diff --git a/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/test.jar b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/test.jar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/test-util/lib/test.jar
diff --git a/jps/jps-builders/testData/output/moduleClasspath/test-util/test-util.iml b/jps/jps-builders/testData/output/moduleClasspath/test-util/test-util.iml
new file mode 100644
index 000000000000..a81119184332
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/test-util/test-util.iml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="module-library" scope="PROVIDED">
+ <library name="provided">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/provided.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library" scope="RUNTIME">
+ <library name="runtime">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/runtime.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library" scope="TEST">
+ <library name="test">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/test.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleClasspath/util/lib/exported.jar b/jps/jps-builders/testData/output/moduleClasspath/util/lib/exported.jar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/util/lib/exported.jar
diff --git a/jps/jps-builders/testData/output/moduleClasspath/util/util.iml b/jps/jps-builders/testData/output/moduleClasspath/util/util.iml
new file mode 100644
index 000000000000..0061ed42307d
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleClasspath/util/util.iml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="module-library" exported="">
+ <library name="exported">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/exported.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="jdk" jdkName="1.5" jdkType="JavaSDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleCycle/module1/module1.iml b/jps/jps-builders/testData/output/moduleCycle/module1/module1.iml
new file mode 100644
index 000000000000..f688a54b5d7c
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/module1/module1.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="module2" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleCycle/module1/src/Bar1.java b/jps/jps-builders/testData/output/moduleCycle/module1/src/Bar1.java
new file mode 100644
index 000000000000..09a608ea6917
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/module1/src/Bar1.java
@@ -0,0 +1,3 @@
+public class Bar1 {
+ private Bar2 bar2;
+}
diff --git a/jps/jps-builders/testData/output/moduleCycle/module2/module2.iml b/jps/jps-builders/testData/output/moduleCycle/module2/module2.iml
new file mode 100644
index 000000000000..3c5e5300787e
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/module2/module2.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="module1" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleCycle/module2/src/Bar2.java b/jps/jps-builders/testData/output/moduleCycle/module2/src/Bar2.java
new file mode 100644
index 000000000000..928afc1637b8
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/module2/src/Bar2.java
@@ -0,0 +1,3 @@
+public class Bar2 {
+ private Bar1 bar1;
+}
diff --git a/jps/jps-builders/testData/output/moduleCycle/moduleCycle.iml b/jps/jps-builders/testData/output/moduleCycle/moduleCycle.iml
new file mode 100644
index 000000000000..d24879e074dc
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/moduleCycle.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="module1" />
+ <orderEntry type="module" module-name="module2" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleCycle/moduleCycle.ipr b/jps/jps-builders/testData/output/moduleCycle/moduleCycle.ipr
new file mode 100644
index 000000000000..3c49f8105681
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/moduleCycle.ipr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/module1/module1.iml" filepath="$PROJECT_DIR$/module1/module1.iml" />
+ <module fileurl="file://$PROJECT_DIR$/module2/module2.iml" filepath="$PROJECT_DIR$/module2/module2.iml" />
+ <module fileurl="file://$PROJECT_DIR$/moduleCycle.iml" filepath="$PROJECT_DIR$/moduleCycle.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/moduleCycle/src/Foo.java b/jps/jps-builders/testData/output/moduleCycle/src/Foo.java
new file mode 100644
index 000000000000..1a8c087d1aa2
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleCycle/src/Foo.java
@@ -0,0 +1,4 @@
+public class Foo {
+ private Bar1 bar1;
+ private Bar2 bar2;
+}
diff --git a/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.iml b/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.iml
new file mode 100644
index 000000000000..26c800ce3109
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.ipr b/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.ipr
new file mode 100644
index 000000000000..d7ee1240ee54
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleTestOutput/moduleTestOutput.ipr
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="tests">
+ <output-path>$ARTIFACTS_OUT$/tests</output-path>
+ <root id="root">
+ <element id="module-test-output" name="moduleTestOutput" />
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/moduleTestOutput.iml" filepath="$PROJECT_DIR$/moduleTestOutput.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/moduleTestOutput/src/MyClass.java b/jps/jps-builders/testData/output/moduleTestOutput/src/MyClass.java
new file mode 100644
index 000000000000..bef6c0e59445
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleTestOutput/src/MyClass.java
@@ -0,0 +1,9 @@
+/**
+ * Created by IntelliJ IDEA.
+ * User: nik
+ * Date: 4/5/11
+ * Time: 4:39 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MyClass {
+}
diff --git a/jps/jps-builders/testData/output/moduleTestOutput/testSrc/MyTest.java b/jps/jps-builders/testData/output/moduleTestOutput/testSrc/MyTest.java
new file mode 100644
index 000000000000..a301f651cc77
--- /dev/null
+++ b/jps/jps-builders/testData/output/moduleTestOutput/testSrc/MyTest.java
@@ -0,0 +1,9 @@
+/**
+ * Created by IntelliJ IDEA.
+ * User: nik
+ * Date: 4/5/11
+ * Time: 4:39 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MyTest {
+}
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/inner.iml b/jps/jps-builders/testData/output/overlappingSourceRoots/inner.iml
new file mode 100644
index 000000000000..e5bee4854eca
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/inner.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$/src/inner">
+ <sourceFolder url="file://$MODULE_DIR$/src/inner/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.iml b/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.iml
new file mode 100644
index 000000000000..b75756ebfc6c
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="inner" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.ipr b/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.ipr
new file mode 100644
index 000000000000..902aa9e065ee
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/overlappingSourceRoots.ipr
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ </component>
+ <component name="CCaseConfig">
+ <option name="checkoutReserved" value="false" />
+ <option name="markExternalChangeAsUpToDate" value="true" />
+ <option name="checkInUseHijack" value="true" />
+ <option name="useUcmModel" value="true" />
+ <option name="synchOutside" value="false" />
+ <option name="isHistoryResticted" value="true" />
+ <option name="useIdenticalSwitch" value="true" />
+ <option name="synchActivitiesOnRefresh" value="true" />
+ <option name="lastScr" value="" />
+ <option name="scrTextFileName" value="" />
+ <option name="historyRevisionsNumber" value="4" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing enabled="false" useClasspath="true" />
+ </component>
+ <component name="CopyrightManager" default="">
+ <module2copyright />
+ </component>
+ <component name="DependencyValidationManager">
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </component>
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+ <component name="EntryPointsManager">
+ <entry_points version="2.0" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="ModuleEditorState">
+ <option name="LAST_EDITED_MODULE_NAME" />
+ <option name="LAST_EDITED_TAB_NAME" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectKey">
+ <option name="state" value="project://default" />
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$//inner.iml" filepath="$PROJECT_DIR$//inner.iml" />
+ <module fileurl="file://$PROJECT_DIR$/overlappingSourceRoots.iml" filepath="$PROJECT_DIR$/overlappingSourceRoots.iml" />
+ </modules>
+ </component>
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+ <component name="SvnConfiguration" maxAnnotateRevisions="500">
+ <option name="USER" value="" />
+ <option name="PASSWORD" value="" />
+ <option name="mySSHConnectionTimeout" value="30000" />
+ <option name="mySSHReadTimeout" value="30000" />
+ <option name="LAST_MERGED_REVISION" />
+ <option name="MERGE_DRY_RUN" value="false" />
+ <option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
+ <option name="UPDATE_LOCK_ON_DEMAND" value="false" />
+ <option name="IGNORE_SPACES_IN_MERGE" value="false" />
+ <option name="DETECT_NESTED_COPIES" value="true" />
+ <option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
+ <option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
+ <option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
+ <option name="FORCE_UPDATE" value="false" />
+ <myIsUseDefaultProxy>false</myIsUseDefaultProxy>
+ </component>
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="" />
+ </component>
+ <component name="VssConfiguration">
+ <option name="CLIENT_PATH" value="" />
+ <option name="SRCSAFEINI_PATH" value="" />
+ <option name="USER_NAME" value="" />
+ <option name="PWD" value="" />
+ <CheckoutOptions>
+ <option name="COMMENT" value="" />
+ <option name="DO_NOT_GET_LATEST_VERSION" value="false" />
+ <option name="REPLACE_WRITABLE" value="false" />
+ <option name="RECURSIVE" value="false" />
+ </CheckoutOptions>
+ <CheckinOptions>
+ <option name="COMMENT" value="" />
+ <option name="KEEP_CHECKED_OUT" value="false" />
+ <option name="RECURSIVE" value="false" />
+ </CheckinOptions>
+ <AddOptions>
+ <option name="STORE_ONLY_LATEST_VERSION" value="false" />
+ <option name="CHECK_OUT_IMMEDIATELY" value="false" />
+ </AddOptions>
+ <UndocheckoutOptions>
+ <option name="MAKE_WRITABLE" value="false" />
+ <option name="REPLACE_LOCAL_COPY" value="2" />
+ <option name="RECURSIVE" value="false" />
+ </UndocheckoutOptions>
+ <GetOptions>
+ <option name="REPLACE_WRITABLE" value="0" />
+ <option name="MAKE_WRITABLE" value="false" />
+ <option name="ANSWER_NEGATIVELY" value="false" />
+ <option name="ANSWER_POSITIVELY" value="false" />
+ <option name="RECURSIVE" value="false" />
+ <option name="VERSION" />
+ </GetOptions>
+ </component>
+ <component name="WebServicesPlugin" addRequiredLibraries="true" />
+ <component name="masterDetails">
+ <states>
+ <state key="GlobalLibrariesConfigurable.UI">
+ <settings>
+ <last-edited>commons-chain-global</last-edited>
+ <splitter-proportions>
+ <option name="proportions">
+ <list>
+ <option value="0.2" />
+ </list>
+ </option>
+ </splitter-proportions>
+ </settings>
+ </state>
+ <state key="JdkListConfigurable.UI">
+ <settings>
+ <last-edited>1.6</last-edited>
+ <splitter-proportions>
+ <option name="proportions">
+ <list>
+ <option value="0.2" />
+ </list>
+ </option>
+ </splitter-proportions>
+ </settings>
+ </state>
+ <state key="ProjectJDKs.UI">
+ <settings>
+ <last-edited>1.5</last-edited>
+ <splitter-proportions>
+ <option name="proportions">
+ <list>
+ <option value="0.2" />
+ </list>
+ </option>
+ </splitter-proportions>
+ </settings>
+ </state>
+ <state key="ProjectLibrariesConfigurable.UI">
+ <settings>
+ <splitter-proportions>
+ <option name="proportions">
+ <list>
+ <option value="0.2" />
+ </list>
+ </option>
+ </splitter-proportions>
+ </settings>
+ </state>
+ </states>
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/b.properties b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/b.properties
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/b.properties
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/Class2.java b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/Class2.java
new file mode 100644
index 000000000000..7b9d77078ffb
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/Class2.java
@@ -0,0 +1,11 @@
+package y;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: nik
+ * Date: 10/4/11
+ * Time: 1:05 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class Class2 {
+}
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/a.properties b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/a.properties
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/src/inner/src/y/a.properties
diff --git a/jps/jps-builders/testData/output/overlappingSourceRoots/src/x/MyClass.java b/jps/jps-builders/testData/output/overlappingSourceRoots/src/x/MyClass.java
new file mode 100644
index 000000000000..9ab66ba56f54
--- /dev/null
+++ b/jps/jps-builders/testData/output/overlappingSourceRoots/src/x/MyClass.java
@@ -0,0 +1,6 @@
+package x;
+
+import y.Class2;
+
+public class MyClass extends Class2 {
+}
diff --git a/jps/jps-builders/testData/output/overwriteTest/data/d1/x.txt b/jps/jps-builders/testData/output/overwriteTest/data/d1/x.txt
new file mode 100644
index 000000000000..562890baa53a
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/data/d1/x.txt
@@ -0,0 +1 @@
+d1 \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/overwriteTest/data/d2/x.txt b/jps/jps-builders/testData/output/overwriteTest/data/d2/x.txt
new file mode 100644
index 000000000000..624c89d7c4d3
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/data/d2/x.txt
@@ -0,0 +1 @@
+d2 \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/overwriteTest/data/dir/a/f.txt b/jps/jps-builders/testData/output/overwriteTest/data/dir/a/f.txt
new file mode 100644
index 000000000000..2e65efe2a145
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/data/dir/a/f.txt
@@ -0,0 +1 @@
+a \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/overwriteTest/data/f.txt b/jps/jps-builders/testData/output/overwriteTest/data/f.txt
new file mode 100644
index 000000000000..63d8dbd40c23
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/data/f.txt
@@ -0,0 +1 @@
+b \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/overwriteTest/dep/dep.iml b/jps/jps-builders/testData/output/overwriteTest/dep/dep.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/dep/dep.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/overwriteTest/dep/src/a.xml b/jps/jps-builders/testData/output/overwriteTest/dep/src/a.xml
new file mode 100644
index 000000000000..a185e52cec98
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/dep/src/a.xml
@@ -0,0 +1 @@
+<root2/> \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/overwriteTest/overwriteTest.iml b/jps/jps-builders/testData/output/overwriteTest/overwriteTest.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/overwriteTest.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/overwriteTest/overwriteTest.ipr b/jps/jps-builders/testData/output/overwriteTest/overwriteTest.ipr
new file mode 100644
index 000000000000..1b0f7c1c8368
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/overwriteTest.ipr
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="dirs">
+ <output-path>$ARTIFACTS_OUT$/dirs</output-path>
+ <root id="root">
+ <element id="dir-copy" path="$PROJECT_DIR$/data/d2" />
+ <element id="dir-copy" path="$PROJECT_DIR$/data/d1" />
+ </root>
+ </artifact>
+ <artifact name="classes">
+ <output-path>$ARTIFACTS_OUT$/classes</output-path>
+ <root id="root">
+ <element id="module-output" name="dep" />
+ <element id="module-output" name="overwriteTest" />
+ </root>
+ </artifact>
+ <artifact name="fileCopy">
+ <output-path>$ARTIFACTS_OUT$/fileCopy</output-path>
+ <root id="root">
+ <element id="directory" name="xxx">
+ <element id="directory" name="a">
+ <element id="file-copy" path="$PROJECT_DIR$/data/f.txt" />
+ </element>
+ <element id="dir-copy" path="$PROJECT_DIR$/data/dir" />
+ </element>
+ </root>
+ </artifact>
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing enabled="false" useClasspath="true" />
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/dep/dep.iml" filepath="$PROJECT_DIR$/dep/dep.iml" />
+ <module fileurl="file://$PROJECT_DIR$/overwriteTest.iml" filepath="$PROJECT_DIR$/overwriteTest.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/overwriteTest/src/a.xml b/jps/jps-builders/testData/output/overwriteTest/src/a.xml
new file mode 100644
index 000000000000..8d3d60bcf499
--- /dev/null
+++ b/jps/jps-builders/testData/output/overwriteTest/src/a.xml
@@ -0,0 +1 @@
+<root1/> \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/pathVariables/external/file.txt b/jps/jps-builders/testData/output/pathVariables/external/file.txt
new file mode 100644
index 000000000000..ac8522fb58c8
--- /dev/null
+++ b/jps/jps-builders/testData/output/pathVariables/external/file.txt
@@ -0,0 +1 @@
+xxx \ No newline at end of file
diff --git a/jps/jps-builders/testData/output/pathVariables/pathVariables.ipr b/jps/jps-builders/testData/output/pathVariables/pathVariables.ipr
new file mode 100644
index 000000000000..047ef1478d4c
--- /dev/null
+++ b/jps/jps-builders/testData/output/pathVariables/pathVariables.ipr
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="fileCopy">
+ <output-path>$ARTIFACTS_OUT$/fileCopy</output-path>
+ <root id="root">
+ <element id="directory" name="dir">
+ <element id="file-copy" path="$EXTERNAL_DIR$/file.txt" />
+ </element>
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/resourceCopying/resourceCopying.iml b/jps/jps-builders/testData/output/resourceCopying/resourceCopying.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/resourceCopying.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/resourceCopying/resourceCopying.ipr b/jps/jps-builders/testData/output/resourceCopying/resourceCopying.ipr
new file mode 100644
index 000000000000..f064ac14edae
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/resourceCopying.ipr
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="/copy/*" />
+ <entry name="*.html" />
+ <entry name="?.txt" />
+ <entry name="copyTree/**/*.txt" />
+ </wildcardResourcePatterns>
+ <annotationProcessing enabled="false" useClasspath="true" />
+ </component>
+ <component name="CopyrightManager" default="">
+ <module2copyright />
+ </component>
+ <component name="DependencyValidationManager">
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </component>
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+ <component name="IdProvider" IDEtalkID="9A54467EA7D9FD19AC02AAADDF3B0B94" />
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="false" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="-Xlint" />
+ <option name="MAXIMUM_HEAP_SIZE" value="512" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/resourceCopying.iml" filepath="$PROJECT_DIR$/resourceCopying.iml" />
+ </modules>
+ </component>
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/a.txt b/jps/jps-builders/testData/output/resourceCopying/src/a.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/a.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/ab.txt b/jps/jps-builders/testData/output/resourceCopying/src/ab.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/ab.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/copy/file.txt b/jps/jps-builders/testData/output/resourceCopying/src/copy/file.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/copy/file.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/copy/subdir/file2.txt b/jps/jps-builders/testData/output/resourceCopying/src/copy/subdir/file2.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/copy/subdir/file2.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/abc.txt b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/abc.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/abc.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/xxx.xml b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/xxx.xml
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/subdir/xxx.xml
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/copyTree/xyz.txt b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/xyz.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/copyTree/xyz.txt
diff --git a/jps/jps-builders/testData/output/resourceCopying/src/index.html b/jps/jps-builders/testData/output/resourceCopying/src/index.html
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/resourceCopying/src/index.html
diff --git a/jps/jps-builders/testData/output/sourceFolderUnderOutput/a.txt b/jps/jps-builders/testData/output/sourceFolderUnderOutput/a.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/jps/jps-builders/testData/output/sourceFolderUnderOutput/a.txt
diff --git a/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.iml b/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.ipr b/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.ipr
new file mode 100644
index 000000000000..375855bbb218
--- /dev/null
+++ b/jps/jps-builders/testData/output/sourceFolderUnderOutput/sourceFolderUnderOutput.ipr
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ArtifactManager">
+ <artifact name="dir">
+ <output-path>$PROJECT_DIR$/</output-path>
+ <root id="root">
+ <element id="file-copy" path="$PROJECT_DIR$/a.txt" />
+ </root>
+ </artifact>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/sourceFolderUnderOutput.iml" filepath="$PROJECT_DIR$/sourceFolderUnderOutput.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/AnnotationTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/AnnotationTest.java
new file mode 100644
index 000000000000..42f2d61b1783
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/AnnotationTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 26.07.11
+ */
+public class AnnotationTest extends IncrementalTestCase {
+ public AnnotationTest() throws Exception {
+ super("annotations");
+ }
+
+ public void testAddAnnotationTarget() throws Exception {
+ doTest();
+ }
+
+ public void testAddAnnotationTypeMemberWithDefaultValue() throws Exception {
+ doTest();
+ }
+
+ public void testAddAnnotationTypeMemberWithDefaultValue2() throws Exception {
+ doTest();
+ }
+
+ public void testAddAnnotationTypeMemberWithoutDefaultValue() throws Exception {
+ doTest();
+ }
+
+ public void testAddDefaultToAnnotationMember() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationRetentionPolicy() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationRetentionPolicy1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationRetentionPolicy2() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationRetentionPolicy3() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationRetentionPolicy4() throws Exception {
+ doTest();
+ }
+
+ public void testChangeAnnotationTypeMemberType() throws Exception {
+ doTest();
+ }
+
+ public void testClassAsArgument() throws Exception {
+ doTest();
+ }
+
+ /* Discussion is needed --- unnecessarily conservative
+ public void testMetaAnnotationChanged() throws Exception {
+ doTest();
+ }
+
+ public void testMetaAnnotationChangedCascade() throws Exception {
+ doTest();
+ }
+
+ public void testMetaAnnotationChangedCascade2() throws Exception {
+ doTest();
+ } */
+
+ public void testRemoveAnnotationTarget() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveAnnotationTypeMember() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveAnnotationTypeMember1() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveDefaultFromAnnotationMember() throws Exception {
+ doTest();
+ }
+
+ public void testConservativeNonIncremental() throws Exception {
+ doTest();
+ }
+
+ public void testConservativeNonIncremental1() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/ClassModifierTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassModifierTest.java
new file mode 100644
index 000000000000..a7d7f2a85354
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassModifierTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 09.08.11
+ */
+public class ClassModifierTest extends IncrementalTestCase {
+ public ClassModifierTest() throws Exception {
+ super("classModifiers");
+ }
+
+ public void testAddStatic() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveStatic() throws Exception {
+ doTest();
+ }
+
+ public void testDecAccess() throws Exception {
+ doTest();
+ }
+
+ public void testSetAbstract() throws Exception {
+ doTest();
+ }
+
+ public void testDropAbstract() throws Exception {
+ doTest();
+ }
+
+ public void testSetFinal() throws Exception {
+ doTest();
+ }
+
+ public void testSetFinal1() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/ClassPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassPropertyTest.java
new file mode 100644
index 000000000000..5a66395e4cf6
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassPropertyTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 09.08.11
+ */
+public class ClassPropertyTest extends IncrementalTestCase {
+ public ClassPropertyTest() throws Exception {
+ super("classProperties");
+ }
+
+ public void testAddExtends() throws Exception {
+ doTest();
+ }
+
+ public void testAddImplements() throws Exception {
+ doTest();
+ }
+
+ public void testChangeExtends() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveExtends() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveExtendsAffectsFieldAccess() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveExtendsAffectsMethodAccess() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveImplements() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveImplements2() throws Exception {
+ doTest();
+ }
+
+ public void testRemoveImplements3() throws Exception {
+ doTest();
+ }
+
+ public void testChangeExtends2() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/ClassRenameTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassRenameTest.java
new file mode 100644
index 000000000000..1dde265f8b63
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/ClassRenameTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 09.08.11
+ */
+public class ClassRenameTest extends IncrementalTestCase {
+ public ClassRenameTest() throws Exception {
+ super("changeName");
+ }
+
+ public void testChangeClassName() {
+ doTest().assertSuccessful();
+ }
+
+ public void testChangeCaseOfName() {
+ doTest().assertSuccessful();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java
new file mode 100644
index 000000000000..29fed9c6bbed
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 22.09.11
+ */
+public class CommonTest extends IncrementalTestCase {
+ public CommonTest() throws Exception {
+ super("common");
+ }
+
+ public void testAnonymous() throws Exception {
+ doTest();
+ }
+
+ public void testChangeDefinitionToClass() throws Exception {
+ doTest();
+ }
+
+ public void testChangeDefinitionToClass2() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClass() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClass1() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClass2() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClassAfterCompileErrors() throws Exception {
+ setupInitialProject();
+
+ doTestBuild(2);
+ }
+
+ public void testDeleteClassPackageDoesntMatchRoot() throws Exception {
+ doTest();
+ }
+
+ public void testInner() throws Exception {
+ doTest();
+ }
+
+ public void testNoResourceDelete() throws Exception {
+ doTest();
+ }
+
+ public void testNoSecondFileCompile() throws Exception {
+ doTest();
+ }
+
+ public void testNoSecondFileCompile1() throws Exception {
+ doTest();
+ }
+
+ public void testDependencyUpdate() throws Exception {
+ doTest();
+ }
+
+ public void testClass2Interface1() throws Exception {
+ doTest();
+ }
+
+ public void testClass2Interface2() throws Exception {
+ doTest();
+ }
+
+ public void testClass2Interface3() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClass3() throws Exception {
+ doTest();
+ }
+
+ public void testDeleteClass4() throws Exception {
+ doTest();
+ }
+
+ public void testAddClass() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/FieldModifierTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/FieldModifierTest.java
new file mode 100644
index 000000000000..bfbf3f491d7f
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/FieldModifierTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 23.09.11
+ */
+public class FieldModifierTest extends IncrementalTestCase {
+ public FieldModifierTest() throws Exception {
+ super("fieldModifiers");
+ }
+
+ public void testSetFinal() throws Exception {
+ doTest();
+ }
+
+ public void testSetPrivate() throws Exception {
+ doTest();
+ }
+
+ public void testSetProtected() throws Exception {
+ doTest();
+ }
+
+ public void testSetStatic() throws Exception {
+ doTest();
+ }
+
+ public void testUnsetStatic() throws Exception {
+ doTest();
+ }
+
+ public void testUnsetStaticFinal() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/FieldPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/FieldPropertyTest.java
new file mode 100644
index 000000000000..918f1213a1ad
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/FieldPropertyTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 23.09.11
+ */
+public class FieldPropertyTest extends IncrementalTestCase {
+ public FieldPropertyTest() throws Exception {
+ super("fieldProperties");
+ }
+
+ public void testConstantChain() throws Exception {
+ doTest();
+ }
+
+ public void testConstantChain1() throws Exception {
+ doTest();
+ }
+
+ public void testConstantChain2() throws Exception {
+ doTest();
+ }
+
+ public void testConstantRemove() throws Exception {
+ doTest();
+ }
+
+ public void testConstantRemove1() throws Exception {
+ doTest();
+ }
+
+ public void testDoubleConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testFloatConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testInnerConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testIntConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testLongConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testNonCompileTimeConstant() throws Exception {
+ doTest();
+ }
+
+ public void testStringConstantChange() throws Exception {
+ doTest();
+ }
+
+ public void testStringConstantLessAccessible() throws Exception {
+ doTest();
+ }
+
+ public void testTypeChange() throws Exception {
+ doTest();
+ }
+
+ public void testTypeChange1() throws Exception {
+ doTest();
+ }
+
+ public void testTypeChange2() throws Exception {
+ doTest();
+ }
+
+ public void testNonIncremental1() throws Exception {
+ doTest();
+ }
+
+ public void testNonIncremental2() throws Exception {
+ doTest();
+ }
+ //public void testNonIncremental3() throws Exception {
+ // doTest();
+ // }
+
+ public void testNonIncremental4() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java
new file mode 100644
index 000000000000..e20d6c0bdce3
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 26.09.11
+ */
+public class GenericTest extends IncrementalTestCase {
+ public GenericTest() throws Exception {
+ super("generics");
+ }
+
+ public void testAddMethodToBase() throws Exception {
+ doTest();
+ }
+
+ public void testAddParameterizedMethodToBase() throws Exception {
+ doTest();
+ }
+
+ public void testChangeBound() throws Exception {
+ doTest();
+ }
+
+ public void testChangeBound1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeBoundClass1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeBoundedClass() throws Exception {
+ doTest();
+ }
+
+ public void testChangeBoundInterface1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeExtends() throws Exception {
+ doTest();
+ }
+
+ public void testChangeExtends1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeExtends2() throws Exception {
+ doTest();
+ }
+
+ public void testChangeImplements() throws Exception {
+ doTest();
+ }
+
+ public void testChangeInterfaceTypeParameter() throws Exception {
+ doTest();
+ }
+
+ public void testChangeToCovariantMethodInBase() throws Exception {
+ doTest();
+ }
+
+ public void testChangeToCovariantMethodInBase2() throws Exception {
+ doTest();
+ }
+
+ /* Not working yet
+ public void testChangeToCovariantMethodInBase3() throws Exception {
+ doTest();
+ }
+ */
+ public void testChangeVarargSignature() throws Exception {
+ doTest();
+ }
+
+ public void testChangeVarargSignature1() throws Exception {
+ doTest();
+ }
+
+ public void testCovariance() throws Exception {
+ doTest();
+ }
+
+ public void testCovariance1() throws Exception {
+ doTest();
+ }
+
+ public void testCovariance2() throws Exception {
+ doTest();
+ }
+
+ public void testCovarianceNoChanges() throws Exception {
+ doTest();
+ }
+
+ public void testDegenerify() throws Exception {
+ doTest();
+ }
+
+ public void testDegenerify1() throws Exception {
+ doTest();
+ }
+
+ public void testFieldTypeChange() throws Exception {
+ doTest();
+ }
+
+ public void testOverrideAnnotatedAnonymous() throws Exception {
+ doTest();
+ }
+
+ /* Not working yet */
+ public void testOverrideAnnotatedAnonymousNotRecompile() throws Exception {
+ doTest();
+ }
+
+ public void testOverrideAnnotatedInner() throws Exception {
+ doTest();
+ }
+
+ public void testParamTypes() throws Exception {
+ doTest();
+ }
+
+ public void testReturnType() throws Exception {
+ doTest();
+ }
+
+ public void testArgumentContainment() throws Exception {
+ doTest();
+ }
+
+ public void testArgumentContainment2() throws Exception {
+ doTest();
+ }
+
+ public void testArgumentContainment3() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/ImportTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/ImportTest.java
new file mode 100644
index 000000000000..9777919fa38f
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/ImportTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * Created with IntelliJ IDEA.
+ * @author: db
+ * Date: 13.02.12
+ * Time: 11:57
+ * To change this template use File | Settings | File Templates.
+ */
+public class ImportTest { //extends IncrementalTestCase {
+ public ImportTest() throws Exception {
+ //super("imports");
+ }
+
+ //public void testClassImport() throws Exception {
+ // doTest();
+ //}
+
+ //public void testStaticImport() throws Exception {
+ // doTest();
+ //}
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
new file mode 100644
index 000000000000..f1cefa112f80
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Processor;
+import org.jetbrains.jps.builders.BuildResult;
+import org.jetbrains.jps.builders.CompileScopeTestBuilder;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaLibraryType;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.PathMacroUtil;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.*;
+
+/**
+ * @author db
+ * @since 26.07.11
+ */
+public abstract class IncrementalTestCase extends JpsBuildTestCase {
+ private final String groupName;
+ private File baseDir;
+ private File workDir;
+ private JpsSdk<JpsDummyElement> myJdk;
+
+ @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
+ protected IncrementalTestCase(final String name) {
+ setName(name);
+ groupName = name;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ baseDir = new File(PathManagerEx.getTestDataPath(getClass()) + File.separator + "compileServer" + File.separator + "incremental" + File.separator + groupName + File.separator + getProjectName());
+ workDir = FileUtil.createTempDirectory("jps-build", null);
+
+ FileUtil.copyDir(baseDir, workDir, new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ String name = file.getName();
+ return !name.endsWith(".new") && !name.endsWith(".delete");
+ }
+ });
+
+ String outputPath = getAbsolutePath("out");
+ JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).setOutputUrl(JpsPathUtil.pathToUrl(outputPath));
+ }
+
+ @Override
+ protected File doGetProjectDir() throws IOException {
+ return workDir;
+ }
+
+ protected String getUrl(String pathRelativeToProjectRoot) {
+ return JpsPathUtil.pathToUrl(getAbsolutePath(pathRelativeToProjectRoot));
+ }
+
+ protected String getAbsolutePath(final String pathRelativeToProjectRoot) {
+ return FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/" + pathRelativeToProjectRoot;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ super.tearDown();
+ }
+ finally {
+ FileUtil.delete(workDir);
+ }
+ }
+
+ private void modify(int stage) {
+ final String removedSuffix = stage == 0? ".remove" : ".remove" + stage;
+ final String newSuffix = stage == 0? ".new" : ".new" + stage;
+
+ FileUtil.processFilesRecursively(baseDir, new Processor<File>() {
+ @Override
+ public boolean process(File file) {
+ if (file.getName().endsWith(removedSuffix)) {
+ FileUtil.delete(getTargetFile(file, removedSuffix));
+ }
+ return true;
+ }
+ });
+ FileUtil.processFilesRecursively(baseDir, new Processor<File>() {
+ @Override
+ public boolean process(File file) {
+ try {
+ if (file.getName().endsWith(newSuffix)) {
+ FileUtil.copyContent(file, getTargetFile(file, newSuffix));
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+ });
+ if (TIMESTAMP_ACCURACY > 1) {
+ try {
+ Thread.sleep(TIMESTAMP_ACCURACY);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+
+ private File getTargetFile(File sourceFile, final String suffix) {
+ String path = FileUtil.getRelativePath(baseDir, sourceFile);
+ assertNotNull(path);
+ if (!path.contains(File.separator)) {
+ path = "src" + File.separator + path;
+ }
+ return new File(workDir, StringUtil.trimEnd(path, suffix));
+ }
+
+ public BuildResult doTest() {
+ setupInitialProject();
+
+ return doTestBuild(1);
+ }
+
+ protected void setupInitialProject() {
+ if (new File(workDir, PathMacroUtil.DIRECTORY_STORE_NAME).exists()) {
+ getOrCreateJdk();
+ loadProject(workDir.getAbsolutePath());
+ }
+ else {
+ addModule();
+ }
+ }
+
+ protected JpsModule addModule() {
+ return addModule(StringUtil.capitalize(getProjectName()), "src");
+ }
+
+ protected JpsModule addModule(final String moduleName, final String srcRootRelativePath) {
+ String srcPath = getAbsolutePath(srcRootRelativePath);
+ return addModule(moduleName, new String[]{srcPath}, null, null, getOrCreateJdk());
+ }
+
+ protected BuildResult doTestBuild(int makesCount) {
+ StringBuilder log = new StringBuilder();
+ String rootPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/";
+ final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new StringProjectBuilderLogger(rootPath, log)));
+ try {
+ doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
+
+ BuildResult result = null;
+
+ for (int idx = 0; idx < makesCount; idx++) {
+ modify(idx);
+ result = doBuild(pd, CompileScopeTestBuilder.make().allModules());
+ }
+
+ assertNotNull(result);
+
+ final ByteArrayOutputStream makeDump = new ByteArrayOutputStream();
+
+ if (result.isSuccessful()) {
+ final PrintStream stream = new PrintStream(makeDump);
+ try {
+ pd.dataManager.getMappings().toStream(stream);
+ }
+ finally {
+ stream.close();
+ }
+ }
+
+ makeDump.close();
+
+ File logFile = new File(baseDir.getAbsolutePath() + ".log");
+ if (!logFile.exists()) {
+ logFile = new File(baseDir, "build.log");
+ }
+ final String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(logFile));
+ final String actual = log.toString();
+
+ assertEquals(expected, actual);
+
+ if (result.isSuccessful()) {
+ doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
+
+ final ByteArrayOutputStream rebuildDump = new ByteArrayOutputStream();
+
+ final PrintStream stream = new PrintStream(rebuildDump);
+ try {
+ pd.dataManager.getMappings().toStream(stream);
+ }
+ finally {
+ stream.close();
+ }
+
+ rebuildDump.close();
+
+ assertEquals(rebuildDump.toString(), makeDump.toString());
+ }
+ return result;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ finally {
+ pd.release();
+ }
+ }
+
+ private JpsSdk<JpsDummyElement> getOrCreateJdk() {
+ if (myJdk == null) {
+ myJdk = addJdk("IDEA jdk");
+ }
+ return myJdk;
+ }
+
+ protected JpsLibrary addLibrary(final String jarPath) {
+ JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ library.addRoot(new File(getAbsolutePath(jarPath)), JpsOrderRootType.COMPILED);
+ return library;
+ }
+
+ protected void addTestRoot(JpsModule module, final String testRootRelativePath) {
+ module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE);
+ }
+
+ private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase {
+ private final String myRoot;
+ private StringBuilder myLog;
+
+ private StringProjectBuilderLogger(String root, StringBuilder log) {
+ myRoot = root;
+ myLog = log;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ protected void logLine(String line) {
+ myLog.append(StringUtil.trimStart(line, myRoot)).append('\n');
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/LogParser.java b/jps/jps-builders/testSrc/org/jetbrains/ether/LogParser.java
new file mode 100644
index 000000000000..5c339e450704
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/LogParser.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 6/29/12
+ */
+public class LogParser {
+
+ private static final String COMPILING_START_STR = "incremental.java.JavaBuilder - Compiling";
+
+ public static void main(String[] args) throws IOException {
+ final String logPath = args[0];
+
+ long totalTime = 0L;
+ int totalFileCount = 0;
+ final BufferedReader reader = new BufferedReader(new FileReader(new File(logPath)));
+ try {
+ String line = reader.readLine();
+ while (line != null) {
+ if (line.contains(COMPILING_START_STR)) {
+ final long startTime = getTime(line);
+ final String nextLine = reader.readLine();
+ if (nextLine != null && nextLine.contains("- Dependency analysis found")) {
+ final long endTime = getTime(nextLine);
+ totalTime += (endTime - startTime);
+ final int index = line.indexOf(COMPILING_START_STR);
+ if (index > 0) {
+ final StringBuilder buf = new StringBuilder();
+ for (int idx = index + COMPILING_START_STR.length(); idx < line.length(); idx++) {
+ final char ch = line.charAt(idx);
+ if (ch == ' ' || ch == '\t') {
+ continue;
+ }
+ if (!Character.isDigit(ch)) {
+ break;
+ }
+ buf.append(ch);
+ }
+ if (buf.length() > 0) {
+ final int fileCount = Integer.parseInt(buf.toString());
+ totalFileCount += fileCount;
+ }
+ }
+ }
+ }
+ line = reader.readLine();
+ }
+ }
+ finally {
+ reader.close();
+ }
+
+ long millis = totalTime % 1000;
+ long seconds = totalTime / 1000;
+ long minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ System.out.println("Files compiled: " + totalFileCount);
+ System.out.println("Total time spent compiling java " + minutes + " min " + seconds + " sec " + millis + " ms");
+ }
+
+
+ private static final int HOURS_START = 11;
+ private static final int MINUTES_START = HOURS_START + 3;
+ private static final int SECONDS_START = MINUTES_START + 3;
+ private static final int MILLIS_START = SECONDS_START + 3;
+
+ private static long getTime(String line) {
+ final int hours = Integer.parseInt(line.substring(HOURS_START, HOURS_START + 2));
+ final int minutes = Integer.parseInt(line.substring(MINUTES_START, MINUTES_START + 2));
+ final int seconds = Integer.parseInt(line.substring(SECONDS_START, SECONDS_START + 2));
+ final int millis = Integer.parseInt(line.substring(MILLIS_START, MILLIS_START + 3));
+ return millis + seconds * 1000 + minutes * 60000 + hours * 3600000;
+ }
+
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java
new file mode 100644
index 000000000000..c7582b815573
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author: db
+ * Date: 04.10.11
+ */
+public class MarkDirtyTest extends IncrementalTestCase {
+ public MarkDirtyTest() throws Exception {
+ super("markDirty");
+ }
+
+ public void testRecompileDependent() {
+ doTest();
+ }
+
+ public void testRecompileDependentTests() {
+ JpsModule module = addModule();
+ addTestRoot(module, "testSrc");
+ JpsLibrary library = addLibrary("lib/a.jar");
+ JpsModuleRootModificationUtil.addDependency(module, library, JpsJavaDependencyScope.TEST, false);
+ doTestBuild(1).assertSuccessful();
+ }
+
+ public void testTransitiveRecompile() {
+ JpsModule module = addModule();
+ addTestRoot(module, "testSrc");
+ JpsModule util = addModule("util", "util/src");
+ addTestRoot(util, "util/testSrc");
+ JpsModuleRootModificationUtil.addDependency(module, util);
+ JpsModule lib = addModule("lib", "lib/src");
+ addTestRoot(lib, "lib/testSrc");
+ JpsModuleRootModificationUtil.addDependency(util, lib);
+ doTestBuild(1).assertSuccessful();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java
new file mode 100644
index 000000000000..1fd356da4a32
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 06.10.11
+ */
+public class MemberChangeTest extends IncrementalTestCase {
+ public MemberChangeTest() {
+ super("membersChange");
+ }
+
+ public void testAddAbstractMethod() {
+ doTest();
+ }
+
+ public void testAddConstructorParameter() {
+ doTest();
+ }
+
+ public void testAddFieldToBaseClass() {
+ doTest();
+ }
+
+ public void testAddFieldToDerived() {
+ doTest();
+ }
+
+ public void testAddFieldToInterface() {
+ doTest();
+ }
+
+ public void testAddFieldToInterface2() {
+ doTest();
+ }
+
+ public void testAddFinalMethodHavingNonFinalMethodInSubclass() {
+ doTest();
+ }
+
+ public void testAddHidingField() {
+ doTest();
+ }
+
+ public void testAddHidingMethod() {
+ doTest();
+ }
+
+ public void testAddInterfaceMethod() {
+ doTest();
+ }
+
+ public void testAddInterfaceMethod2() {
+ doTest();
+ }
+
+ public void testAddLessAccessibleFieldToDerived() {
+ doTest();
+ }
+
+ public void testAddMethodWithIncompatibleReturnType() {
+ doTest();
+ }
+
+ public void testAddMethodWithCovariantReturnType() {
+ doTest();
+ }
+
+ public void testAddMoreAccessibleMethodToBase() {
+ doTest();
+ }
+
+ public void testAddMoreSpecific() {
+ doTest();
+ }
+
+ public void testAddMoreSpecific1() {
+ doTest();
+ }
+
+ public void testAddMoreSpecific2() {
+ doTest();
+ }
+
+ public void testAddNonStaticMethodHavingStaticMethodInSubclass() {
+ doTest();
+ }
+
+ public void testAddStaticFieldToDerived() {
+ doTest();
+ }
+
+ public void testChangeStaticMethodSignature() {
+ doTest();
+ }
+
+ public void testChangeMethodGenericReturnType() {
+ doTest();
+ }
+
+ public void testDeleteConstructor() {
+ doTest();
+ }
+
+ public void testDeleteInner() {
+ doTest();
+ }
+
+ public void testDeleteMethod() {
+ doTest();
+ }
+
+ public void testDeleteInterfaceMethod() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation2() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation3() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation4() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation5() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation6() {
+ doTest();
+ }
+
+ public void testDeleteMethodImplementation7() {
+ doTest();
+ }
+
+ public void testHierarchy() {
+ doTest();
+ }
+
+ public void testHierarchy2() {
+ doTest();
+ }
+
+ public void testRemoveBaseImplementation() {
+ doTest();
+ }
+
+ public void testRemoveHidingField() {
+ doTest();
+ }
+
+ public void testRemoveHidingMethod() {
+ doTest();
+ }
+
+ public void testRenameMethod() {
+ doTest();
+ }
+
+ public void testMoveMethodToSubclass() {
+ doTest().assertSuccessful();
+ }
+
+ public void testThrowsListDiffersInBaseAndDerived() {
+ doTest();
+ }
+
+ public void testRemoveThrowsInBaseMethod() {
+ doTest();
+ }
+
+ public void testAddMethod() {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodModifierTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodModifierTest.java
new file mode 100644
index 000000000000..77136f8a8c31
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodModifierTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 04.10.11
+ */
+public class MethodModifierTest extends IncrementalTestCase {
+ public MethodModifierTest() throws Exception {
+ super("methodModifiers");
+ }
+
+ public void testDecConstructorAccess() throws Exception {
+ doTest();
+ }
+
+ public void testIncAccess() throws Exception {
+ doTest();
+ }
+
+ public void testSetAbstract() throws Exception {
+ doTest();
+ }
+
+ public void testSetFinal() throws Exception {
+ doTest();
+ }
+
+ public void testSetPrivate() throws Exception {
+ doTest();
+ }
+
+ public void testSetProtected() throws Exception {
+ doTest();
+ }
+
+
+ public void testUnsetFinal() throws Exception {
+ doTest();
+ }
+
+ public void testUnsetStatic() throws Exception {
+ doTest();
+ }
+
+ public void testSetStatic() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java
new file mode 100644
index 000000000000..28093d91f8b8
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 05.10.11
+ */
+public class MethodPropertyTest extends IncrementalTestCase {
+ public MethodPropertyTest() throws Exception {
+ super("methodProperties");
+ }
+
+ public void testAddThrows() throws Exception {
+ doTest();
+ }
+
+ public void testChangeReturnType() throws Exception {
+ doTest();
+ }
+
+ public void testChangeReturnType1() throws Exception {
+ doTest();
+ }
+
+ public void testChangeSignature() throws Exception {
+ doTest();
+ }
+
+ public void testChangeSignature1() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/PackageInfoTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/PackageInfoTest.java
new file mode 100644
index 000000000000..8c72207cfc12
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/PackageInfoTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+/**
+ * @author: db
+ * Date: 04.10.11
+ */
+public class PackageInfoTest extends IncrementalTestCase {
+ public PackageInfoTest() throws Exception {
+ super("packageInfo");
+ }
+
+ public void testPackageInfoNoRecompile() throws Exception {
+ doTest();
+ }
+
+ public void testPackageInfoNoRecompile2() throws Exception {
+ doTest();
+ }
+
+ public void testPackageInfoRecompileOnConstantChange() throws Exception {
+ doTest();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/StorageDumper.java b/jps/jps-builders/testSrc/org/jetbrains/ether/StorageDumper.java
new file mode 100644
index 000000000000..5c6d772cc354
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/StorageDumper.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.ether;
+
+import org.jetbrains.jps.builders.java.dependencyView.Mappings;
+
+import java.io.File;
+
+/**
+ * @author: db
+ * Date: 14.05.12
+ */
+public class StorageDumper {
+ private static class Env {
+ final String myProjectPath;
+ final String myOutputPath;
+ final String myErrors;
+ final boolean myHelp;
+
+ Env(final String[] args) {
+ int s = 0;
+
+ String projectPath = null;
+ String outputPath = null;
+ boolean help = false;
+
+ final StringBuilder errors = new StringBuilder();
+
+ for (final String arg : args) {
+ switch (s) {
+ case 0: // Initial state
+ if (arg.equals("-o")) {
+ s = 1;
+ }
+ else if (arg.equals("-h")) {
+ help = true;
+ }
+ else if (arg.startsWith("-")) {
+ errors.append("Unrecognized option: ");
+ errors.append(arg);
+ errors.append("\n");
+ }
+ else {
+ if (projectPath != null) {
+ errors.append("Multiple storage paths specified, skipping ");
+ errors.append(arg);
+ errors.append("\n");
+ }
+ else {
+ projectPath = arg;
+ }
+ }
+ break;
+
+ case 1: // -o
+ if (arg.startsWith("-")) {
+ errors.append("Output path expected after \"-o\", but found: ");
+ errors.append(arg);
+ errors.append("\n");
+ }
+ else {
+ if (outputPath != null) {
+ errors.append("Multiple output paths specified, skipping ");
+ errors.append(arg);
+ errors.append("\n");
+ }
+ else {
+ outputPath = arg;
+ }
+ }
+ s = 0;
+ }
+ }
+
+ myOutputPath = outputPath;
+ myProjectPath = projectPath;
+ myHelp = help;
+
+ myErrors = errors.toString();
+ }
+
+ String getProjectPath() {
+ return myProjectPath;
+ }
+
+ String getOutputPath() {
+ return myOutputPath;
+ }
+
+ String getErrors() {
+ return myErrors;
+ }
+
+ void report() {
+ if (myHelp) {
+ System.out.println("Usage: <executable> [-o <output-path> | -h ] <storage-path>");
+ System.out.println();
+ }
+
+ System.err.println(myErrors);
+ }
+ }
+
+ public static void main(final String[] args) {
+ final Env env = new Env(args);
+
+ env.report();
+
+ final String dataPath = env.getProjectPath();
+ final String oath = env.getOutputPath();
+
+ if (dataPath == null) {
+ System.err.println("No project path specified.");
+ }
+ else {
+ try {
+ final File parent = new File(oath == null ? "" : oath);
+ final File dataStorageRoot = new File(dataPath, "mappings");
+
+ final Mappings mappings = new Mappings(dataStorageRoot, true);
+ try {
+ //final File outputPath = new File(parent, "snapshot-" + new SimpleDateFormat("dd-MM-yy(hh-mm-ss)").format(new Date()) + ".log");
+ //FileUtil.createIfDoesntExist(outputPath);
+ //final PrintStream p = new PrintStream(outputPath);
+ //mappings.toStream(p);
+ //p.close();
+ mappings.toStream(parent);
+ }
+ finally {
+ mappings.close();
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java
new file mode 100644
index 000000000000..56b936246fd5
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Function;
+import junit.framework.Assert;
+import org.jetbrains.jps.incremental.MessageHandler;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.DoneSomethingNotification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author nik
+*/
+public class BuildResult implements MessageHandler {
+ private final List<BuildMessage> myErrorMessages;
+ private final List<BuildMessage> myInfoMessages;
+ private boolean myUpToDate = true;
+
+ public BuildResult() {
+ myErrorMessages = new ArrayList<BuildMessage>();
+ myInfoMessages = new ArrayList<BuildMessage>();
+ }
+
+ @Override
+ public void processMessage(BuildMessage msg) {
+ if (msg.getKind() == BuildMessage.Kind.ERROR) {
+ myErrorMessages.add(msg);
+ myUpToDate = false;
+ }
+ else {
+ myInfoMessages.add(msg);
+ }
+ if (msg instanceof DoneSomethingNotification) {
+ myUpToDate = false;
+ }
+ }
+
+ public void assertUpToDate() {
+ Assert.assertTrue("Project sources weren't up to date", myUpToDate);
+ }
+
+ public void assertFailed() {
+ Assert.assertFalse("Build not failed as expected", isSuccessful());
+ }
+
+ public boolean isSuccessful() {
+ return myErrorMessages.isEmpty();
+ }
+
+ public void assertSuccessful() {
+ final Function<BuildMessage,String> toStringFunction = StringUtil.createToStringFunction(BuildMessage.class);
+ Assert.assertTrue("Build failed. \nErrors:\n" + StringUtil.join(myErrorMessages, toStringFunction, "\n") +
+ "\nInfo messages:\n" + StringUtil.join(myInfoMessages, toStringFunction, "\n"), isSuccessful());
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java
new file mode 100644
index 000000000000..8e49ab4ef8cf
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import org.jetbrains.jps.api.BuildType;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.incremental.CompileScope;
+import org.jetbrains.jps.incremental.CompileScopeImpl;
+import org.jetbrains.jps.incremental.ModuleBuildTarget;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class CompileScopeTestBuilder {
+ private BuildType myBuildType;
+ private Set<BuildTargetType<?>> myTargetTypes = new HashSet<BuildTargetType<?>>();
+ private Set<BuildTarget<?>> myTargets = new HashSet<BuildTarget<?>>();
+
+ public static CompileScopeTestBuilder rebuild() {
+ return new CompileScopeTestBuilder(BuildType.PROJECT_REBUILD);
+ }
+
+ public static CompileScopeTestBuilder make() {
+ return new CompileScopeTestBuilder(BuildType.MAKE);
+ }
+
+ public static CompileScopeTestBuilder recompile() {
+ return new CompileScopeTestBuilder(BuildType.FORCED_COMPILATION);
+ }
+
+ private CompileScopeTestBuilder(BuildType buildType) {
+ myBuildType = buildType;
+ }
+
+ public BuildType getBuildType() {
+ return myBuildType;
+ }
+
+ public CompileScopeTestBuilder allModules() {
+ myTargetTypes.addAll(JavaModuleBuildTargetType.ALL_TYPES);
+ return this;
+ }
+
+ public CompileScopeTestBuilder module(JpsModule module) {
+ myTargets.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION));
+ myTargets.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST));
+ return this;
+ }
+
+ public CompileScopeTestBuilder allArtifacts() {
+ myTargetTypes.add(ArtifactBuildTargetType.INSTANCE);
+ return this;
+ }
+
+ public CompileScopeTestBuilder artifact(JpsArtifact artifact) {
+ myTargets.add(new ArtifactBuildTarget(artifact));
+ return this;
+ }
+
+ public CompileScope build() {
+ return new CompileScopeImpl(myBuildType != BuildType.MAKE, myTargetTypes, myTargets, Collections.<BuildTarget<?>,Set<File>>emptyMap());
+ }
+
+ public CompileScopeTestBuilder all() {
+ myTargetTypes.addAll(BuilderRegistry.getInstance().getTargetTypes());
+ return this;
+ }
+
+ public CompileScopeTestBuilder artifacts(JpsArtifact[] artifacts) {
+ for (JpsArtifact artifact : artifacts) {
+ myTargets.add(new ArtifactBuildTarget(artifact));
+ }
+ return this;
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy
new file mode 100644
index 000000000000..80770ee36359
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders
+
+import org.jetbrains.jps.builders.rebuild.JpsRebuildTestCase
+
+/**
+ * @author nik
+ */
+class JavacFileEncodingTest extends JpsRebuildTestCase {
+ public void test() {
+ doTest("javacFileEncoding/javacFileEncoding.ipr", {
+ dir("production") {
+ dir("javacFileEncoding") {
+ file("MyClass.class")
+ }
+ }
+ })
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
new file mode 100644
index 000000000000..54528ada8d5e
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileSystemUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.testFramework.UsefulTestCase;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.io.TestFileSystemBuilder;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.BuildType;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.impl.BuildDataPathsImpl;
+import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
+import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl;
+import org.jetbrains.jps.builders.logging.BuildLoggingManager;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ClasspathBootstrap;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.BuilderRegistry;
+import org.jetbrains.jps.incremental.IncProjectBuilder;
+import org.jetbrains.jps.incremental.RebuildRequestedException;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
+import org.jetbrains.jps.incremental.storage.BuildTargetsState;
+import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.indices.impl.IgnoredFileIndexImpl;
+import org.jetbrains.jps.indices.impl.ModuleExcludeIndexImpl;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsProjectLoader;
+import org.jetbrains.jps.model.serialization.PathMacroUtil;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.jetbrains.jps.builders.CompileScopeTestBuilder.make;
+
+/**
+ * @author nik
+ */
+public abstract class JpsBuildTestCase extends UsefulTestCase {
+ protected static final long TIMESTAMP_ACCURACY = SystemInfo.isMac ? 1000 : 1;
+ private File myProjectDir;
+ protected JpsProject myProject;
+ protected JpsModel myModel;
+ private JpsSdk<JpsDummyElement> myJdk;
+ private File myDataStorageRoot;
+ private TestProjectBuilderLogger myLogger;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myModel = JpsElementFactory.getInstance().createModel();
+ myProject = myModel.getProject();
+ myDataStorageRoot = FileUtil.createTempDirectory("compile-server-" + getProjectName(), null);
+ myLogger = new TestProjectBuilderLogger();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ myProjectDir = null;
+ super.tearDown();
+ }
+
+ protected static void assertOutput(final String outputPath, TestFileSystemBuilder expected) {
+ expected.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(outputPath)));
+ }
+
+ protected static void assertOutput(JpsModule module, TestFileSystemBuilder expected) {
+ String outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false);
+ assertNotNull(outputUrl);
+ assertOutput(JpsPathUtil.urlToPath(outputUrl), expected);
+ }
+
+ protected static void change(String filePath) {
+ change(filePath, null);
+ }
+
+ protected static void change(String filePath, final @Nullable String newContent) {
+ try {
+ File file = new File(FileUtil.toSystemDependentName(filePath));
+ assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists());
+ if (newContent != null) {
+ FileUtil.writeToFile(file, newContent);
+ }
+ long oldTimestamp = FileSystemUtil.lastModified(file);
+ long time = System.currentTimeMillis();
+ setLastModified(file, time);
+ if (FileSystemUtil.lastModified(file) <= oldTimestamp) {
+ setLastModified(file, time + TIMESTAMP_ACCURACY);
+ long newTimeStamp = FileSystemUtil.lastModified(file);
+ assertTrue("Failed to change timestamp for " + file.getAbsolutePath(), newTimeStamp > oldTimestamp);
+ long delta;
+ while ((delta = newTimeStamp - System.currentTimeMillis()) > 0) {
+ try {
+ //we need this to ensure that the file won't be treated as changed by user during compilation and marked for recompilation
+ //noinspection BusyWait
+ Thread.sleep(delta);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void setLastModified(File file, long time) {
+ boolean updated = file.setLastModified(time);
+ assertTrue("Cannot modify timestamp for " + file.getAbsolutePath(), updated);
+ }
+
+ protected static void delete(String filePath) {
+ File file = new File(FileUtil.toSystemDependentName(filePath));
+ assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists());
+ final boolean deleted = FileUtil.delete(file);
+ assertTrue("Cannot delete file " + file.getAbsolutePath(), deleted);
+ }
+
+ protected JpsSdk<JpsDummyElement> addJdk(final String name) {
+ try {
+ return addJdk(name, FileUtil.toSystemIndependentName(ClasspathBootstrap.getResourceFile(Object.class).getCanonicalPath()));
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected JpsSdk<JpsDummyElement> addJdk(final String name, final String path) {
+ String homePath = System.getProperty("java.home");
+ String versionString = System.getProperty("java.version");
+ JpsTypedLibrary<JpsSdk<JpsDummyElement>> jdk = myModel.getGlobal().addSdk(name, homePath, versionString, JpsJavaSdkType.INSTANCE);
+ jdk.addRoot(JpsPathUtil.pathToUrl(path), JpsOrderRootType.COMPILED);
+ return jdk.getProperties();
+ }
+
+ protected String getProjectName() {
+ return StringUtil.decapitalize(StringUtil.trimStart(getName(), "test"));
+ }
+
+ protected ProjectDescriptor createProjectDescriptor(final BuildLoggingManager buildLoggingManager) {
+ try {
+ BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(myModel);
+ ModuleExcludeIndex index = new ModuleExcludeIndexImpl(myModel);
+ IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(myModel);
+ BuildDataPaths dataPaths = new BuildDataPathsImpl(myDataStorageRoot);
+ BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, myModel, index, dataPaths, ignoredFileIndex);
+ BuildTargetsState targetsState = new BuildTargetsState(dataPaths, myModel, buildRootIndex);
+ ProjectTimestamps timestamps = new ProjectTimestamps(myDataStorageRoot, targetsState);
+ BuildDataManager dataManager = new BuildDataManager(dataPaths, targetsState, true);
+ return new ProjectDescriptor(myModel, new BuildFSState(true), timestamps, dataManager, buildLoggingManager, index, targetsState,
+ targetIndex, buildRootIndex, ignoredFileIndex);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void loadProject(String projectPath) {
+ loadProject(projectPath, Collections.<String, String>emptyMap());
+ }
+
+ protected void loadProject(String projectPath,
+ Map<String, String> pathVariables) {
+ try {
+ String testDataRootPath = getTestDataRootPath();
+ String fullProjectPath = FileUtil.toSystemDependentName(testDataRootPath != null ? testDataRootPath + "/" + projectPath : projectPath);
+ Map<String, String> allPathVariables = new HashMap<String, String>(pathVariables.size() + 1);
+ allPathVariables.putAll(pathVariables);
+ allPathVariables.put(PathMacroUtil.APPLICATION_HOME_DIR, PathManager.getHomePath());
+ addPathVariables(allPathVariables);
+ JpsProjectLoader.loadProject(myProject, allPathVariables, fullProjectPath);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void addPathVariables(Map<String, String> pathVariables) {
+ }
+
+ @Nullable
+ protected String getTestDataRootPath() {
+ return null;
+ }
+
+ protected JpsModule addModule(String moduleName,
+ String[] srcPaths,
+ @Nullable String outputPath,
+ @Nullable String testOutputPath,
+ JpsSdk<JpsDummyElement> jdk) {
+ JpsModule module = myProject.addModule(moduleName, JpsJavaModuleType.INSTANCE);
+ module.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, jdk.createReference());
+ module.getDependenciesList().addSdkDependency(JpsJavaSdkType.INSTANCE);
+ if (srcPaths.length > 0) {
+ for (String srcPath : srcPaths) {
+ module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(srcPath));
+ module.addSourceRoot(JpsPathUtil.pathToUrl(srcPath), JavaSourceRootType.SOURCE);
+ }
+ JpsJavaModuleExtension extension = JpsJavaExtensionService.getInstance().getOrCreateModuleExtension(module);
+ if (outputPath != null) {
+ extension.setOutputUrl(JpsPathUtil.pathToUrl(outputPath));
+ if (!StringUtil.isEmpty(testOutputPath)) {
+ extension.setTestOutputUrl(JpsPathUtil.pathToUrl(testOutputPath));
+ }
+ else {
+ extension.setTestOutputUrl(extension.getOutputUrl());
+ }
+ }
+ else {
+ extension.setInheritOutput(true);
+ }
+ }
+ return module;
+ }
+
+ protected void rebuildAll() {
+ doBuild(CompileScopeTestBuilder.rebuild().all()).assertSuccessful();
+ }
+
+ protected BuildResult makeAll() {
+ return doBuild(make().all());
+ }
+
+ protected BuildResult doBuild(CompileScopeTestBuilder scope) {
+ ProjectDescriptor descriptor = createProjectDescriptor(new BuildLoggingManager(myLogger));
+ try {
+ myLogger.clear();
+ return doBuild(descriptor, scope);
+ }
+ finally {
+ descriptor.release();
+ }
+ }
+
+ protected void assertCompiled(String builderName, String... paths) {
+ myLogger.assertCompiled(builderName, new File[]{myProjectDir, myDataStorageRoot}, paths);
+ }
+
+ protected void assertDeleted(String... paths) {
+ myLogger.assertDeleted(new File[]{myProjectDir, myDataStorageRoot}, paths);
+ }
+
+ protected BuildResult doBuild(final ProjectDescriptor descriptor, CompileScopeTestBuilder scopeBuilder) {
+ IncProjectBuilder builder = new IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL, null);
+ BuildResult result = new BuildResult();
+ builder.addMessageHandler(result);
+ try {
+ builder.build(scopeBuilder.build(), scopeBuilder.getBuildType() == BuildType.MAKE, scopeBuilder.getBuildType() == BuildType.PROJECT_REBUILD, false);
+ }
+ catch (RebuildRequestedException e) {
+ throw new RuntimeException(e);
+ }
+ return result;
+ }
+
+ protected String createFile(String relativePath) {
+ return createFile(relativePath, "");
+ }
+
+ protected String createFile(String relativePath, final String text) {
+ try {
+ File file = new File(getOrCreateProjectDir(), relativePath);
+ FileUtil.writeToFile(file, text);
+ return FileUtil.toSystemIndependentName(file.getAbsolutePath());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected String copyToProject(String relativeSourcePath, String relativeTargetPath) {
+ File source = PathManagerEx.findFileUnderProjectHome(relativeSourcePath, getClass());
+ String fullTargetPath = getAbsolutePath(relativeTargetPath);
+ File target = new File(fullTargetPath);
+ try {
+ if (source.isDirectory()) {
+ FileUtil.copyDir(source, target);
+ }
+ else {
+ FileUtil.copy(source, target);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return fullTargetPath;
+ }
+
+ private File getOrCreateProjectDir() {
+ if (myProjectDir == null) {
+ try {
+ myProjectDir = doGetProjectDir();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return myProjectDir;
+ }
+
+ protected File doGetProjectDir() throws IOException {
+ return FileUtil.createTempDirectory("prj", null);
+ }
+
+ protected String getAbsolutePath(final String pathRelativeToProjectRoot) {
+ return FileUtil.toSystemIndependentName(new File(getOrCreateProjectDir(), pathRelativeToProjectRoot).getAbsolutePath());
+ }
+
+ protected JpsModule addModule(String moduleName, String... srcPaths) {
+ if (myJdk == null) {
+ myJdk = addJdk("1.6");
+ }
+ return addModule(moduleName, srcPaths, getAbsolutePath("out/production/" + moduleName), null, myJdk);
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy
new file mode 100644
index 000000000000..6c33c437cfd7
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.groovy
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders
+import com.intellij.openapi.util.io.FileUtil
+import org.jetbrains.jps.ModuleChunk
+import org.jetbrains.jps.ProjectPaths
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
+import org.jetbrains.jps.builders.rebuild.JpsRebuildTestCase
+import org.jetbrains.jps.incremental.ModuleBuildTarget
+/**
+ * @author nik
+ */
+public class ModuleClasspathTest extends JpsRebuildTestCase {
+ @Override
+ protected void setUp() {
+ super.setUp()
+ myModel.getGlobal().getLibraryCollection().findLibrary("1.6").delete()
+ addJdk("1.6", "/jdk.jar")
+ addJdk("1.5", "/jdk15.jar")
+ loadProject("moduleClasspath/moduleClasspath.ipr")
+ }
+
+ private String getProjectPath() {
+ return FileUtil.toSystemIndependentName(getTestDataRootPath()) + "/moduleClasspath/moduleClasspath.ipr"
+ }
+
+ public void testSimpleClasspath() {
+ assertClasspath('util', false, ["util/lib/exported.jar", "/jdk15.jar"])
+ }
+
+ public void testScopes() {
+ assertClasspath("test-util", false,
+ ["/jdk.jar", "test-util/lib/provided.jar"])
+ assertClasspath("test-util", true,
+ ["/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"])
+ }
+
+ public void testDepModules() {
+ assertClasspath("main", false,
+ ["util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"])
+ assertClasspath("main", true,
+ ["out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar",
+ "out/test/test-util", "out/production/test-util", "main/lib/service.jar"])
+ }
+
+ public void testCompilationClasspath() {
+ ModuleChunk chunk = createChunk('main')
+ assertClasspath(["util/lib/exported.jar", "out/production/util", "/jdk.jar"],
+ getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
+ assertClasspath(["main/lib/service.jar"],
+ getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
+ }
+
+ private def assertClasspath(String moduleName, boolean includeTests, List<String> expected) {
+ ModuleChunk chunk = createChunk(moduleName)
+ final List<String> classpath = getPathsList(new ProjectPaths().getCompilationClasspathFiles(chunk, includeTests, true, true))
+ assertClasspath(expected, toSystemIndependentPaths(classpath))
+ }
+
+ private ModuleChunk createChunk(String moduleName) {
+ def module = myProject.modules.find {it.name == moduleName}
+ return new ModuleChunk([new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION)] as Set)
+ }
+
+ private def assertClasspath(List<String> expected, List<String> classpath) {
+ String basePath = FileUtil.toSystemIndependentName(new File(getProjectPath()).parentFile.absolutePath) + "/"
+ List<String> actual = toSystemIndependentPaths(classpath).collect { String path ->
+ path.startsWith(basePath) ? path.substring(basePath.length()) : path
+ }
+ assertEquals(expected.join("\n"), actual.join("\n"))
+ }
+
+ private static List<String> toSystemIndependentPaths(List<String> classpath) {
+ final List<String> result = new ArrayList<String>()
+ for (String path: classpath) {
+ result.add(FileUtil.toSystemIndependentName(path));
+ }
+ return result
+ }
+
+ public static List<String> getPathsList(Collection<File> files) {
+ final List<String> result = new ArrayList<String>();
+ for (File file : files) {
+ result.add(getCanonicalPath(file));
+ }
+ return result;
+ }
+ private static String getCanonicalPath(File file) {
+ final String path = file.getPath();
+ return path.contains(".")? FileUtil.toCanonicalPath(path) : FileUtil.toSystemIndependentName(path);
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/TestProjectBuilderLogger.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/TestProjectBuilderLogger.java
new file mode 100644
index 000000000000..4d7613623c4a
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/TestProjectBuilderLogger.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.UsefulTestCase;
+import com.intellij.util.containers.MultiMap;
+import gnu.trove.THashSet;
+import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class TestProjectBuilderLogger extends ProjectBuilderLoggerBase {
+ private MultiMap<String, File> myCompiledFiles = new MultiMap<String, File>();
+ private Set<File> myDeletedFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+ @Override
+ public void logDeletedFiles(Collection<String> paths) {
+ for (String path : paths) {
+ myDeletedFiles.add(new File(path));
+ }
+ }
+
+ @Override
+ public void logCompiledFiles(Collection<File> files, String builderName, String description) throws IOException {
+ myCompiledFiles.putValues(builderName, files);
+ }
+
+ public void clear() {
+ myCompiledFiles.clear();
+ myDeletedFiles.clear();
+ }
+
+ public void assertCompiled(String builderName, File[] baseDirs, String... paths) {
+ assertRelativePaths(baseDirs, myCompiledFiles.get(builderName), paths);
+ }
+
+ public void assertDeleted(File[] baseDirs, String... paths) {
+ assertRelativePaths(baseDirs, myDeletedFiles, paths);
+ }
+
+ private static void assertRelativePaths(File[] baseDirs, Collection<File> files, String[] expected) {
+ List<String> relativePaths = new ArrayList<String>();
+ for (File file : files) {
+ String path = file.getAbsolutePath();
+ for (File baseDir : baseDirs) {
+ if (baseDir != null && FileUtil.isAncestor(baseDir, file, false)) {
+ path = FileUtil.getRelativePath(baseDir, file);
+ break;
+ }
+ }
+ relativePaths.add(FileUtil.toSystemIndependentName(path));
+ }
+ UsefulTestCase.assertSameElements(relativePaths, expected);
+ }
+
+ @Override
+ protected void logLine(String message) {
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/java/ForcedCompilationTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/java/ForcedCompilationTest.java
new file mode 100644
index 000000000000..613b2db9c3c9
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/java/ForcedCompilationTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.java;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.builders.CompileScopeTestBuilder;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public class ForcedCompilationTest extends JpsBuildTestCase {
+ public void testRecompileDependentAfterForcedCompilation() {
+ String srcRoot = PathUtil.getParentPath(createFile("src/A.java", "class A{ { new B(); } }"));
+ String b = createFile("depSrc/B.java", "public class B{}");
+ JpsModule main = addModule("main", srcRoot);
+ JpsModule dep = addModule("dep", PathUtil.getParentPath(b));
+ main.getDependenciesList().addModuleDependency(dep);
+ rebuildAll();
+
+ change(b, "public class B{ public B(int i){} }");
+ doBuild(CompileScopeTestBuilder.recompile().module(dep)).assertSuccessful();
+ doBuild(CompileScopeTestBuilder.make().module(main)).assertFailed();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy
new file mode 100644
index 000000000000..5f4de621d724
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.rebuild
+
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.util.io.ZipUtil
+
+import java.util.jar.Attributes
+import java.util.jar.Manifest
+/**
+ * @author nik
+ */
+class ArtifactRebuildTest extends JpsRebuildTestCase {
+ public void testArtifactIncludesArchiveArtifact() {
+ def name = "artifactIncludesArchiveArtifact"
+ try {
+ doTest("$name/${name}.ipr", {
+ dir("artifacts") {
+ dir("data") {
+ archive("a.jar") {
+ file("a.txt")
+ }
+ }
+ }
+ })
+ }
+ finally {
+ FileUtil.delete(new File(FileUtil.toSystemDependentName(getTestDataRootPath() + "/$name/data/a.jar")))
+ }
+ }
+
+ public void testArtifactWithoutOutput() {
+ def outDir = FileUtil.createTempDirectory("output", "").absolutePath
+ loadProject("artifactWithoutOutput/artifactWithoutOutput.ipr", ["OUTPUT_DIR":outDir])
+
+ rebuild()
+ assertOutput(outDir, {
+ dir("artifacts") {
+ dir("main") {
+ file("data.txt")
+ file("data2.txt")
+ }
+ }
+ })
+ }
+
+ public void testExtractDir() {
+ doTest("extractDirTest/extractDirTest.ipr", {
+ dir("artifacts") {
+ dir("extractDir") {
+ file("b.txt", "b")
+ }
+ dir("extractRoot") {
+ dir("extracted") {
+ dir("dir") {
+ file("b.txt", "b")
+ }
+ file("a.txt", "a")
+ }
+ }
+ dir("packedDir") {
+ archive("packedDir.jar") {
+ file("b.txt", "b")
+ }
+ }
+ dir("packedRoot") {
+ archive("packedRoot.jar") {
+ dir("dir") {
+ file("b.txt", "b")
+ }
+ file("a.txt", "a")
+ }
+ }
+ }
+ })
+ }
+
+ public void testManifestInArtifact() {
+ loadAndRebuild("manifestInArtifact/manifest.ipr", [:])
+ File jarFile = new File(myOutputDirectory, "artifacts/simple/simple.jar")
+ junit.framework.Assert.assertTrue(jarFile.exists())
+ File extracted = FileUtil.createTempDirectory("build-manifest", "")
+ ZipUtil.extract(jarFile, extracted, null)
+ File manifestFile = new File(extracted, "META-INF/MANIFEST.MF")
+ junit.framework.Assert.assertTrue(manifestFile.exists())
+ Manifest manifest = new Manifest(new FileInputStream(manifestFile))
+ junit.framework.Assert.assertEquals("MyClass", manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS))
+ }
+
+ public void testOverwriteArtifacts() {
+ doTest("overwriteTest/overwriteTest.ipr", {
+ dir("artifacts") {
+ dir("classes") {
+ file("a.xml", "<root2/>")
+ }
+ dir("dirs") {
+ file("x.txt", "d2")
+ }
+ dir("fileCopy") {
+ dir("xxx") {
+ dir("a") {
+ file("f.txt", "b")
+ }
+ }
+ }
+ }
+ dir("production") {
+ dir("dep") {
+ file("a.xml", "<root2/>")
+ }
+ dir("overwriteTest") {
+ file("a.xml", "<root1/>")
+ }
+ }
+ })
+ }
+
+ public void testPathVariablesInArtifact() {
+ String externalDir = "${getTestDataRootPath()}/pathVariables/external"
+ doTest("pathVariables/pathVariables.ipr", ["EXTERNAL_DIR": externalDir], {
+ dir("artifacts") {
+ dir("fileCopy") {
+ dir("dir") {
+ file("file.txt", "xxx")
+ }
+ }
+ }
+ })
+ }
+
+ public void testModuleTestOutputElement() {
+ doTest("moduleTestOutput/moduleTestOutput.ipr", {
+ dir("artifacts") {
+ dir("tests") {
+ file("MyTest.class")
+ }
+ }
+ dir("production") {
+ dir("moduleTestOutput") {
+ file("MyClass.class")
+ }
+ }
+ dir("test") {
+ dir("moduleTestOutput") {
+ file("MyTest.class")
+ }
+ }
+ })
+ }
+
+ //todo[nik] fix
+ public void _testSourceRootUnderOutput() throws Exception {
+ loadProject("sourceFolderUnderOutput/sourceFolderUnderOutput.ipr", [:])
+ try {
+ rebuild()
+ junit.framework.Assert.fail("Cleaning should fail")
+ }
+ catch (Exception ignored) {
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
new file mode 100644
index 000000000000..5af8263c03c5
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.rebuild
+import com.intellij.openapi.application.ex.PathManagerEx
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.util.io.TestFileSystemBuilder
+import org.jetbrains.jps.util.JpsPathUtil
+import org.jetbrains.jps.builders.JpsBuildTestCase
+import org.jetbrains.jps.model.java.JpsJavaExtensionService
+/**
+ * @author nik
+ */
+abstract class JpsRebuildTestCase extends JpsBuildTestCase {
+ protected File myOutputDirectory;
+
+ @Override
+ protected void setUp() {
+ super.setUp()
+ addJdk("1.6")
+ }
+
+ def doTest(String projectPath, Closure expectedOutput) {
+ doTest(projectPath, [:], expectedOutput)
+ }
+
+ def doTest(String projectPath, Map<String, String> pathVariables, Closure expectedOutput) {
+ loadAndRebuild(projectPath, pathVariables)
+ assertOutput(getOrCreateOutputDirectory().getAbsolutePath(), expectedOutput);
+ }
+
+ def protected assertOutput(String targetFolder, Closure expectedOutput) {
+ def root = TestFileSystemBuilder.fs()
+ initFileSystemItem(root, expectedOutput)
+ root.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(targetFolder)))
+ }
+
+ protected void loadAndRebuild(String projectPath, Map<String, String> pathVariables) {
+ loadProject(projectPath, pathVariables)
+ rebuild()
+ }
+
+ protected void rebuild() {
+ JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath()))
+ rebuildAll()
+ }
+
+ private File getOrCreateOutputDirectory() {
+ if (myOutputDirectory == null) {
+ myOutputDirectory = FileUtil.createTempDirectory("jps-build-output", "")
+ }
+ myOutputDirectory
+ }
+
+ @Override
+ protected void addPathVariables(Map<String, String> pathVariables) {
+ pathVariables.put("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().absolutePath) + "/artifacts")
+ }
+
+ @Override
+ protected String getTestDataRootPath() {
+ return PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output").absolutePath
+ }
+
+ def initFileSystemItem(TestFileSystemBuilder item, Closure initializer) {
+ def meta = new Expando()
+ meta.dir = {String name, Closure content ->
+ initFileSystemItem(item.dir(name), content)
+ }
+ meta.archive = {String name, Closure content ->
+ initFileSystemItem(item.archive(name), content)
+ }
+ meta.file = {Object[] args ->
+ item.file((String)args[0], (String)args.length > 1 ? args[1] : null)
+ }
+
+ initializer.delegate = meta
+ initializer.setResolveStrategy Closure.DELEGATE_FIRST
+ initializer()
+ }
+
+ def File createTempFile() {
+ return FileUtil.createTempFile("jps-build-file", "");
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy
new file mode 100644
index 000000000000..36e03eb0890b
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.rebuild
+/**
+ * @author nik
+ */
+public class ModuleRebuildTest extends JpsRebuildTestCase {
+ public void testModuleCycle() {
+ doTest("moduleCycle/moduleCycle.ipr", {
+ dir("production") {
+ dir("module1") {
+ file("Bar1.class")
+ }
+ dir("module2") {
+ file("Bar2.class")
+ }
+ dir("moduleCycle") {
+ file("Foo.class")
+ }
+ }
+ })
+ }
+
+ public void testOverlappingSourceRoots() {
+ doTest("overlappingSourceRoots/overlappingSourceRoots.ipr", {
+ dir("production") {
+ dir("inner") {
+ dir("y") {
+ file("a.properties")
+ file("Class2.class")
+ }
+ }
+ dir("overlappingSourceRoots") {
+ dir("x") {
+ file("MyClass.class")
+ }
+ }
+ }
+ })
+ }
+
+ public void testResourceCopying() {
+ doTest("resourceCopying/resourceCopying.ipr", {
+ dir("production") {
+ dir("resourceCopying") {
+ dir("copy") {
+ file("file.txt")
+ }
+ dir("copyTree") {
+ dir("subdir") {
+ file("abc.txt")
+ }
+ file("xyz.txt")
+ }
+ file("a.txt")
+ file("index.html")
+ }
+ }
+ })
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java
new file mode 100644
index 000000000000..8ba0678ab673
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.resources;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
+
+import static com.intellij.util.io.TestFileSystemItem.fs;
+
+/**
+ * @author nik
+ */
+public class ResourceCopyingTest extends JpsBuildTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(myProject).addResourcePattern("*.xml");
+ }
+
+ public void testSimple() {
+ String file = createFile("src/a.xml");
+ JpsModule m = addModule("m", PathUtil.getParentPath(file));
+ rebuildAll();
+ assertOutput(m, fs().file("a.xml"));
+ }
+ public void testPackagePrefix() {
+ String file = createFile("src/a.xml");
+ JpsModule m = addModule("m", PathUtil.getParentPath(file));
+ JpsModuleSourceRoot sourceRoot = assertOneElement(m.getSourceRoots());
+ JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> typed = sourceRoot.asTyped(JavaSourceRootType.SOURCE);
+ assertNotNull(typed);
+ typed.getProperties().setData(new JavaSourceRootProperties("xxx"));
+ rebuildAll();
+ assertOutput(m, fs().dir("xxx").file("a.xml"));
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java
new file mode 100644
index 000000000000..0c27e91e532d
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import static com.intellij.util.io.TestFileSystemBuilder.fs;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+/**
+ * @author nik
+ */
+public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase {
+ public void testOverwriteArchives() {
+ final String aFile = createFile("aaa.txt", "a");
+ final String bFile = createFile("bbb.txt", "b");
+ final JpsArtifact a = addArtifact(
+ root()
+ .archive("x.jar").fileCopy(aFile).end()
+ .archive("x.jar")
+ .fileCopy(bFile));
+ buildAll();
+ assertOutput(a, fs()
+ .archive("x.jar")
+ .file("aaa.txt", "a")
+ );
+ buildAllAndAssertUpToDate();
+
+ change(aFile, "a2");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/x.jar", "aaa.txt");
+ assertOutput(a, fs().archive("x.jar").file("aaa.txt", "a2"));
+ buildAllAndAssertUpToDate();
+
+ change(bFile, "b2");
+ buildAllAndAssertUpToDate();
+
+ delete(bFile);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testOverwriteNestedArchive() {
+ final String cFile = createFile("c.txt", "c");
+ final String eFile = createFile("e.txt", "e");
+ final JpsArtifact a = addArtifact(
+ root()
+ .archive("a.jar").archive("b.jar").fileCopy(cFile).end().end()
+ .archive("a.jar").archive("d.jar").fileCopy(eFile));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.txt", "c"));
+ buildAllAndAssertUpToDate();
+
+ change(eFile, "e2");
+ buildAllAndAssertUpToDate();
+
+ change(cFile, "c2");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.jar", "c.txt");
+ assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.txt", "c2"));
+ buildAllAndAssertUpToDate();
+
+ delete(eFile);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testOverwriteFileByArchive() {
+ final String xFile = createFile("x.txt", "1");
+ final String jarFile = createFile("lib/junit.jar", "123");
+ JpsArtifact a = addArtifact(root()
+ .archive("junit.jar").fileCopy(xFile).end().parentDirCopy(jarFile));
+ buildAll();
+ assertOutput(a, fs().archive("junit.jar").file("x.txt", "1"));
+ buildAllAndAssertUpToDate();
+
+ change(xFile, "2");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/junit.jar", "x.txt");
+ assertOutput(a, fs().archive("junit.jar").file("x.txt", "2"));
+ buildAllAndAssertUpToDate();
+
+ change(jarFile, "321");
+ buildAllAndAssertUpToDate();
+
+ delete(jarFile);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testOverwriteArchiveByFile() {
+ final String xFile = createFile("d/x.txt", "1");
+ final String jarFile = createFile("lib/jdom.jar", "123");
+ JpsArtifact a = addArtifact(root().parentDirCopy(jarFile)
+ .archive("jdom.jar").parentDirCopy(xFile));
+ buildAll();
+ assertOutput(a, fs().file("jdom.jar", "123"));
+ buildAllAndAssertUpToDate();
+
+ change(xFile, "2");
+ buildAllAndAssertUpToDate();
+
+ change(jarFile, "321");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/jdom.jar", "lib/jdom.jar");
+ assertOutput(a, fs().file("jdom.jar", "321"));
+ buildAllAndAssertUpToDate();
+
+ delete(xFile);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testFileOrder() {
+ final String firstFile = createFile("d1/xxx.txt", "first");
+ final String secondFile = createFile("d2/xxx.txt", "second");
+ final String fooFile = createFile("d3/xxx.txt", "foo");
+ final JpsArtifact a = addArtifact(
+ root().dir("ddd")
+ .dirCopy(PathUtil.getParentPath(firstFile))
+ .dirCopy(PathUtil.getParentPath(fooFile)).parentDirCopy(secondFile).end()
+ );
+ buildAll();
+ assertOutput(a, fs().dir("ddd").file("xxx.txt", "first"));
+ buildAllAndAssertUpToDate();
+
+ change(firstFile, "first2");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/ddd/xxx.txt", "d1/xxx.txt");
+ assertOutput(a, fs().dir("ddd").file("xxx.txt", "first2"));
+ buildAllAndAssertUpToDate();
+
+ change(secondFile);
+ buildAllAndAssertUpToDate();
+
+ change(fooFile);
+ buildAllAndAssertUpToDate();
+
+ delete(fooFile);
+ buildAllAndAssertUpToDate();
+
+ delete(secondFile);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testDeleteOverwritingFiles() {
+ final String firstFile = createFile("d1/xxx.txt", "1");
+ final String secondFile = createFile("d2/xxx.txt", "2");
+ final JpsArtifact a = addArtifact("a",
+ root().dir("ddd").dirCopy(PathUtil.getParentPath(firstFile)).parentDirCopy(secondFile).fileCopy(createFile("y.txt"))
+ );
+ buildAll();
+ assertOutput(a, fs().dir("ddd").file("xxx.txt", "1").file("y.txt"));
+
+ delete(firstFile);
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/ddd/xxx.txt", "d2/xxx.txt");
+ assertOutput(a, fs().dir("ddd").file("xxx.txt", "2").file("y.txt"));
+ buildAllAndAssertUpToDate();
+
+ delete(secondFile);
+ buildAll();
+ assertDeleted("out/artifacts/a/ddd/xxx.txt");
+ assertOutput(a, fs().dir("ddd").file("y.txt"));
+ }
+
+ public void testUpdateManifest() {
+ final String manifestText1 = "Manifest-Version: 1.0\r\nMain-Class: A\r\n\r\n";
+ final String manifest = createFile("d/MANIFEST.MF", manifestText1);
+ final JpsArtifact a = addArtifact("a", root().archive("a.jar").dir("META-INF").parentDirCopy(manifest).fileCopy(createFile("a.txt")));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").dir("META-INF").file("MANIFEST.MF", manifestText1).file("a.txt"));
+
+ final String manifestText2 = "Manifest-Version: 1.0\r\nMain-Class: B\r\n\r\n";
+ change(manifest, manifestText2);
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.jar", "d/MANIFEST.MF", "a.txt");
+ assertOutput(a, fs().archive("a.jar").dir("META-INF").file("MANIFEST.MF", manifestText2).file("a.txt"));
+ buildAllAndAssertUpToDate();
+
+ delete(manifest);
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.jar", "a.txt");
+ assertOutput(a, fs().archive("a.jar").dir("META-INF").file("a.txt"));
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java
new file mode 100644
index 000000000000..9179999c9000
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import static com.intellij.util.io.TestFileSystemBuilder.fs;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+/**
+ * @author nik
+ */
+public class ArtifactBuilderTest extends ArtifactBuilderTestCase {
+ public void testFileCopy() {
+ final JpsArtifact a = addArtifact(root().fileCopy(createFile("file.txt", "foo")));
+ buildAll();
+ assertOutput(a, fs().file("file.txt", "foo"));
+ }
+
+ public void testDir() {
+ final JpsArtifact a = addArtifact(
+ root()
+ .fileCopy(createFile("abc.txt"))
+ .dir("dir")
+ .fileCopy(createFile("xxx.txt", "bar"))
+ );
+ buildAll();
+ assertOutput(a, fs()
+ .file("abc.txt")
+ .dir("dir")
+ .file("xxx.txt", "bar")
+ );
+ }
+
+ public void testArchive() {
+ final JpsArtifact a = addArtifact(
+ root()
+ .archive("xxx.zip")
+ .fileCopy(createFile("X.class", "data"))
+ .dir("dir")
+ .fileCopy(createFile("Y.class"))
+ );
+ buildAll();
+ assertOutput(a, fs()
+ .archive("xxx.zip")
+ .file("X.class", "data")
+ .dir("dir")
+ .file("Y.class")
+ );
+ }
+
+ public void testTwoDirsInArchive() {
+ final String dir1 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir1/a/x.txt")));
+ final String dir2 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir2/a/y.txt")));
+ final JpsArtifact a = addArtifact(
+ root()
+ .archive("a.jar")
+ .dirCopy(dir1)
+ .dirCopy(dir2)
+ .dir("a").fileCopy(createFile("z.txt"))
+ );
+ buildAll();
+ assertOutput(a, fs()
+ .archive("a.jar")
+ .dir("a")
+ .file("x.txt")
+ .file("y.txt")
+ .file("z.txt")
+ );
+ }
+
+ public void testArchiveInArchive() {
+ final JpsArtifact a = addArtifact(
+ root()
+ .archive("a.jar")
+ .archive("b.jar")
+ .fileCopy(createFile("xxx.txt", "foo"))
+ );
+ buildAll();
+ assertOutput(a, fs()
+ .archive("a.jar")
+ .archive("b.jar")
+ .file("xxx.txt", "foo")
+ );
+ }
+
+ public void testIncludedArtifact() {
+ final JpsArtifact included = addArtifact("included",
+ root()
+ .fileCopy(createFile("aaa.txt")));
+ final JpsArtifact a = addArtifact(
+ root()
+ .dir("dir")
+ .artifact(included)
+ .end()
+ .fileCopy(createFile("bbb.txt"))
+ );
+ buildAll();
+
+ assertOutput(included, fs().file("aaa.txt"));
+ assertOutput(a, fs()
+ .dir("dir")
+ .file("aaa.txt")
+ .end()
+ .file("bbb.txt")
+ );
+ }
+
+ public void testMergeDirectories() {
+ final JpsArtifact included = addArtifact("included",
+ root().dir("dir").fileCopy(createFile("aaa.class")));
+ final JpsArtifact a = addArtifact(
+ root()
+ .artifact(included)
+ .dir("dir")
+ .fileCopy(createFile("bbb.class")));
+ buildAll();
+ assertOutput(a, fs()
+ .dir("dir")
+ .file("aaa.class")
+ .file("bbb.class")
+ );
+ }
+
+ public void testCopyLibrary() {
+ final JpsLibrary library = addProjectLibrary("lib", getJUnitJarPath());
+ final JpsArtifact a = addArtifact(root().lib(library));
+ buildAll();
+ assertOutput(a, fs().file("junit.jar"));
+ }
+
+ public void testModuleOutput() {
+ final String file = createFile("src/A.java", "public class A {}");
+ final JpsModule module = addModule("a", PathUtil.getParentPath(file));
+ final JpsArtifact artifact = addArtifact(root().module(module));
+
+ buildArtifacts(artifact);
+ assertOutput(artifact, fs().file("A.class"));
+ }
+
+ public void testCopyResourcesFromModuleOutput() {
+ String file = createFile("src/a.xml", "");
+ JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(myProject).addResourcePattern("*.xml");
+ JpsModule module = addModule("a", PathUtil.getParentPath(file));
+ JpsArtifact artifact = addArtifact(root().module(module));
+ buildArtifacts(artifact);
+ assertOutput(artifact, fs().file("a.xml"));
+ }
+
+ public void testIgnoredFile() {
+ final String file = createFile("a/.svn/a.txt");
+ createFile("a/svn/b.txt");
+ final JpsArtifact a = addArtifact(root().parentDirCopy(PathUtil.getParentPath(file)));
+ buildAll();
+ assertOutput(a, fs().dir("svn").file("b.txt"));
+ }
+
+ public void testIgnoredFileInArchive() {
+ final String file = createFile("a/.svn/a.txt");
+ createFile("a/svn/b.txt");
+ final JpsArtifact a = addArtifact(archive("a.jar").parentDirCopy(PathUtil.getParentPath(file)));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").dir("svn").file("b.txt"));
+ }
+
+ public void testCopyExcludedFolder() {
+ //explicitly added excluded files should be copied (e.g. compile output)
+ final String file = createFile("xxx/excluded/a.txt");
+ createFile("xxx/excluded/CVS");
+ final String excluded = PathUtil.getParentPath(file);
+ final String dir = PathUtil.getParentPath(excluded);
+
+ final JpsModule module = addModule("myModule");
+ module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir));
+ module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(excluded));
+
+ final JpsArtifact a = addArtifact(root().dirCopy(excluded));
+ buildAll();
+ assertOutput(a, fs().file("a.txt"));
+ }
+
+ public void testCopyExcludedFile() {
+ //excluded files under non-excluded directory should not be copied
+ final String file = createFile("xxx/excluded/a.txt");
+ createFile("xxx/b.txt");
+ createFile("xxx/CVS");
+ final String dir = PathUtil.getParentPath(PathUtil.getParentPath(file));
+
+ JpsModule module = addModule("myModule");
+ module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir));
+ module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(PathUtil.getParentPath(file)));
+
+ final JpsArtifact a = addArtifact(root().dirCopy(dir));
+ buildAll();
+ assertOutput(a, fs().file("b.txt"));
+ }
+
+ public void testExtractDirectory() {
+ final JpsArtifact a = addArtifact("a", root().dir("dir").extractedDir(getJUnitJarPath(), "/junit/textui/"));
+ buildAll();
+ assertOutput(a, fs().dir("dir")
+ .file("ResultPrinter.class")
+ .file("TestRunner.class"));
+ }
+
+ public void testExtractDirectoryFromExcludedJar() throws IOException {
+ String jarPath = createFile("dir/lib/j.jar");
+ FileUtil.copy(new File(getJUnitJarPath()), new File(jarPath));
+ JpsModule module = addModule("m");
+ String libDir = PathUtil.getParentPath(jarPath);
+ module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(PathUtil.getParentPath(libDir)));
+ module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(libDir));
+ final JpsArtifact a = addArtifact("a", root().extractedDir(jarPath, "/junit/textui/"));
+ buildAll();
+ assertOutput(a, fs().file("ResultPrinter.class")
+ .file("TestRunner.class"));
+ }
+
+ public void testPackExtractedDirectory() {
+ final JpsArtifact a = addArtifact("a", root().archive("a.jar").extractedDir(getJUnitJarPath(), "/junit/textui/"));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar")
+ .file("ResultPrinter.class")
+ .file("TestRunner.class"));
+ }
+
+ public void testSelfIncludingArtifact() {
+ final JpsArtifact a = addArtifact("a", root());
+ LayoutElementTestUtil.addArtifactToLayout(a, a);
+ assertBuildFailed(a);
+ }
+
+ public void testCircularInclusion() {
+ final JpsArtifact a = addArtifact("a", root());
+ final JpsArtifact b = addArtifact("b", root());
+ LayoutElementTestUtil.addArtifactToLayout(a, b);
+ LayoutElementTestUtil.addArtifactToLayout(b, a);
+ assertBuildFailed(a);
+ assertBuildFailed(b);
+ }
+
+ public void testArtifactContainingSelfIncludingArtifact() {
+ JpsArtifact c = addArtifact("c", root());
+ final JpsArtifact a = addArtifact("a", root().artifact(c));
+ LayoutElementTestUtil.addArtifactToLayout(a, a);
+ final JpsArtifact b = addArtifact("b", root().artifact(a));
+
+ buildArtifacts(c);
+ assertBuildFailed(b);
+ assertBuildFailed(a);
+ }
+
+ public void testArtifactContainingSelfIncludingArtifactWithoutOutput() {
+ final JpsArtifact a = addArtifact("a", root());
+ LayoutElementTestUtil.addArtifactToLayout(a, a);
+ final JpsArtifact b = addArtifact("b", root().artifact(a));
+ a.setOutputPath(null);
+
+ assertBuildFailed(b);
+ }
+
+ //IDEA-73893
+ public void testManifestFileIsFirstEntry() throws IOException {
+ final String firstFile = createFile("src/A.txt");
+ final String manifestFile = createFile("src/MANIFEST.MF");
+ final String lastFile = createFile("src/Z.txt");
+ final JpsArtifact a = addArtifact(archive("a.jar").dir("META-INF")
+ .fileCopy(firstFile).fileCopy(manifestFile).fileCopy(lastFile));
+ buildArtifacts(a);
+ final String jarPath = a.getOutputPath() + "/a.jar";
+ JarFile jarFile = new JarFile(new File(jarPath));
+ try {
+ final Enumeration<JarEntry> entries = jarFile.entries();
+ assertTrue(entries.hasMoreElements());
+ final JarEntry firstEntry = entries.nextElement();
+ assertEquals(JarFile.MANIFEST_NAME, firstEntry.getName());
+ }
+ finally {
+ jarFile.close();
+ }
+ }
+
+ public void testPreserveCompressionMethodForEntryExtractedFromOneArchiveAndPackedIntoAnother() throws IOException {
+ String path = createFile("data/a.jar");
+ ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(new File(path))));
+ try {
+ ZipEntry entry = new ZipEntry("a.txt");
+ byte[] text = "text".getBytes();
+ entry.setMethod(ZipEntry.STORED);
+ entry.setSize(text.length);
+ CRC32 crc32 = new CRC32();
+ crc32.update(text);
+ entry.setCrc(crc32.getValue());
+ output.putNextEntry(entry);
+ output.write(text);
+ output.closeEntry();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ output.close();
+ }
+ JpsArtifact a = addArtifact(archive("b.jar").extractedDir(path, ""));
+ buildAll();
+ assertOutput(a, fs().archive("b.jar").file("a.txt", "text"));
+
+ final String jarPath = a.getOutputPath() + "/b.jar";
+ ZipFile zipFile = new ZipFile(new File(jarPath));
+ try {
+ ZipEntry entry = zipFile.getEntry("a.txt");
+ assertNotNull(entry);
+ assertEquals(ZipEntry.STORED, entry.getMethod());
+ }
+ finally {
+ zipFile.close();
+ }
+ }
+
+ public void testBuildModuleBeforeArtifactIfSomeDirectoryInsideModuleOutputIsCopiedToArtifact() {
+ String src = PathUtil.getParentPath(PathUtil.getParentPath(createFile("src/x/A.java", "package x; class A{}")));
+ JpsModule module = addModule("m", src);
+ File output = JpsJavaExtensionService.getInstance().getOutputDirectory(module, false);
+ JpsArtifact artifact = addArtifact(root().dirCopy(new File(output, "x").getAbsolutePath()));
+ rebuildAll();
+ assertOutput(module, fs().dir("x").file("A.class"));
+ assertOutput(artifact, fs().file("A.class"));
+ }
+
+ public void testClearOutputOnRebuild() throws IOException {
+ String file = createFile("d/a.txt");
+ JpsArtifact a = addArtifact(root().parentDirCopy(file));
+ buildAll();
+ createFileInArtifactOutput(a, "b.txt");
+ buildAllAndAssertUpToDate();
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+
+ rebuildAll();
+ assertOutput(a, fs().file("a.txt"));
+ }
+
+ public void testDeleteOnlyOutputFileOnRebuildForArchiveArtifact() throws IOException {
+ String file = createFile("a.txt");
+ JpsArtifact a = addArtifact(archive("a.jar").fileCopy(file));
+ buildAll();
+ createFileInArtifactOutput(a, "b.txt");
+ buildAllAndAssertUpToDate();
+ assertOutput(a, fs().archive("a.jar").file("a.txt").end().file("b.txt"));
+
+ rebuildAll();
+ assertOutput(a, fs().archive("a.jar").file("a.txt").end().file("b.txt"));
+ }
+
+ public void testDoNotCreateEmptyArchive() {
+ String file = createFile("dir/a.txt");
+ JpsArtifact a = addArtifact(archive("a.jar").parentDirCopy(file));
+ delete(file);
+ buildAll();
+ assertEmptyOutput(a);
+ }
+
+ public void testDoNotCreateEmptyArchiveInsideArchive() {
+ String file = createFile("dir/a.txt");
+ JpsArtifact a = addArtifact(archive("a.jar").archive("inner.jar").parentDirCopy(file));
+ delete(file);
+ buildAll();
+ assertEmptyOutput(a);
+ }
+
+ public void testDoNotCreateEmptyArchiveFromExtractedDirectory() {
+ final JpsArtifact a = addArtifact("a", archive("a.jar").dir("dir").extractedDir(getJUnitJarPath(), "/xxx/"));
+ buildAll();
+ assertEmptyOutput(a);
+ }
+
+ private static void createFileInArtifactOutput(JpsArtifact a, final String fileName) throws IOException {
+ assertTrue(new File(a.getOutputPath(), fileName).createNewFile());
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java
new file mode 100644
index 000000000000..473c09d606cb
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.io.TestFileSystemBuilder;
+import com.intellij.util.text.UniqueNameGenerator;
+import org.jetbrains.jps.builders.CompileScopeTestBuilder;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.artifact.DirectoryArtifactType;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.java.JpsJavaLibraryType;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.intellij.util.io.TestFileSystemItem.fs;
+
+/**
+ * @author nik
+ */
+public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase {
+ @Override
+ protected void tearDown() throws Exception {
+ for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(myProject)) {
+ String outputPath = artifact.getOutputPath();
+ if (outputPath != null) {
+ FileUtil.delete(new File(FileUtil.toSystemDependentName(outputPath)));
+ }
+ }
+ super.tearDown();
+ }
+
+ protected JpsArtifact addArtifact(LayoutElementTestUtil.LayoutElementCreator root) {
+ Set<String> usedNames = getArtifactNames();
+ final String name = UniqueNameGenerator.generateUniqueName("a", usedNames);
+ return addArtifact(name, root);
+ }
+
+ private Set<String> getArtifactNames() {
+ Set<String> usedNames = new HashSet<String>();
+ for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(myProject)) {
+ usedNames.add(artifact.getName());
+ }
+ return usedNames;
+ }
+
+ protected JpsArtifact addArtifact(String name, LayoutElementTestUtil.LayoutElementCreator root) {
+ assertFalse("JpsArtifact " + name + " already exists", getArtifactNames().contains(name));
+ JpsArtifact artifact = JpsArtifactService.getInstance().addArtifact(myProject, name, root.buildElement(), DirectoryArtifactType.INSTANCE,
+ JpsElementFactory.getInstance().createDummyElement());
+ artifact.setOutputPath(getAbsolutePath("out/artifacts/" + name));
+ return artifact;
+ }
+
+ protected JpsLibrary addProjectLibrary(String name, String jarPath) {
+ final JpsLibrary library = myProject.getLibraryCollection().addLibrary(name, JpsJavaLibraryType.INSTANCE);
+ library.addRoot(JpsPathUtil.pathToUrl(jarPath), JpsOrderRootType.COMPILED);
+ return library;
+ }
+
+ protected void buildAll() {
+ Collection<JpsArtifact> artifacts = JpsArtifactService.getInstance().getArtifacts(myProject);
+ buildArtifacts(artifacts.toArray(new JpsArtifact[artifacts.size()]));
+ }
+
+ protected void buildArtifacts(JpsArtifact... artifacts) {
+ doBuild(CompileScopeTestBuilder.make().allModules().artifacts(artifacts)).assertSuccessful();
+ }
+
+ protected static String getJUnitJarPath() {
+ final File file = PathManager.findFileInLibDirectory("junit.jar");
+ assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists());
+ return FileUtil.toSystemIndependentName(file.getAbsolutePath());
+ }
+
+ protected static void assertEmptyOutput(JpsArtifact a) {
+ assertOutput(a, fs());
+ }
+
+ protected void assertBuildFailed(JpsArtifact a) {
+ doBuild(CompileScopeTestBuilder.make().allModules().artifact(a)).assertFailed();
+ }
+
+ protected void assertCopied(String... filePaths) {
+ assertDeletedAndCopied(ArrayUtil.EMPTY_STRING_ARRAY, filePaths);
+ }
+
+ protected void assertDeletedAndCopied(String deletedPath, String... copiedPaths) {
+ assertDeletedAndCopied(new String[]{deletedPath}, copiedPaths);
+ }
+
+ protected void assertDeletedAndCopied(String[] deletedPaths, String... copiedPaths) {
+ assertCompiled(IncArtifactBuilder.BUILDER_NAME, copiedPaths);
+ super.assertDeleted(deletedPaths);
+ }
+
+ @Override
+ protected void assertDeleted(String... paths) {
+ assertDeletedAndCopied(paths);
+ }
+
+ protected static void assertOutput(JpsArtifact a, TestFileSystemBuilder expected) {
+ assertOutput(a.getOutputPath(), expected);
+ }
+
+ protected void buildAllAndAssertUpToDate() {
+ buildAll();
+ assertUpToDate();
+ }
+
+ protected void assertUpToDate() {
+ assertDeletedAndCopied(ArrayUtil.EMPTY_STRING_ARRAY);
+ }
+
+ protected static void rename(String path, String newName) {
+ try {
+ File file = new File(FileUtil.toSystemDependentName(path));
+ assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists());
+ final File tempFile = new File(file.getParentFile(), "__" + newName);
+ FileUtil.rename(file, tempFile);
+ FileUtil.copyContent(tempFile, new File(file.getParentFile(), newName));
+ FileUtil.delete(tempFile);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/CleanArtifactOutputOnRebuildTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/CleanArtifactOutputOnRebuildTest.java
new file mode 100644
index 000000000000..0b297c19afd9
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/CleanArtifactOutputOnRebuildTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+
+import static com.intellij.util.io.TestFileSystemBuilder.fs;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+/**
+ * @author nik
+ */
+public class CleanArtifactOutputOnRebuildTest extends ArtifactBuilderTestCase {
+
+ public void testCleanOutput() {
+ JpsArtifact a = addArtifact(root().fileCopy(createFile("a.txt")));
+ buildArtifacts(a);
+ createFileInArtifactOutput(a, "b.txt");
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+
+ rebuildAll();
+ assertOutput(a, fs().file("a.txt"));
+ }
+
+ public void testDoNotCleanOnRebuildIfOptionIsSwitchedOff() {
+ JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(myProject).setClearOutputDirectoryOnRebuild(false);
+ JpsArtifact a = addArtifact(root().fileCopy(createFile("a.txt")));
+ buildArtifacts(a);
+ createFileInArtifactOutput(a, "b.txt");
+ rebuildAll();
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+ }
+
+ public void testDoNotCleanIfContainsSourceFolder() {
+ JpsArtifact a = addArtifact(root().fileCopy(createFile("a.txt")));
+ addModule("m", a.getOutputPath() + "/src");
+ buildArtifacts(a);
+ createFileInArtifactOutput(a, "b.txt");
+ rebuildAll();
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+ }
+
+ public void testDoNotCleanIfContainsArtifactRoot() {
+ JpsModule m = addModule("m");
+ String resDir = PathUtil.getParentPath(createFile("res/a.txt"));
+ m.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(resDir));
+ JpsArtifact a = addArtifact(root().dirCopy(resDir));
+ a.setOutputPath(resDir);
+ buildArtifacts(a);
+ assertOutput(a, fs().file("a.txt"));
+
+ createFile("res/b.txt");
+ rebuildAll();
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+ }
+
+ public void testCleanArtifactOutputIfItIsIncludedIntoAnotherArtifact() {
+ JpsArtifact included = addArtifact("b", root().fileCopy(createFile("a.txt")));
+ JpsArtifact a = addArtifact(root().artifact(included));
+ buildArtifacts(a, included);
+ createFileInArtifactOutput(included, "b.txt");
+ assertOutput(included, fs().file("a.txt").file("b.txt"));
+ rebuildAll();
+ assertOutput(included, fs().file("a.txt"));
+ }
+
+ public void testCleanModuleOutputIfItIsIncludedInArtifact() {
+ String file = createFile("src/A.java", "class A{}");
+ JpsModule m = addModule("m", PathUtil.getParentPath(file));
+ JpsArtifact a = addArtifact(root().module(m));
+ buildArtifacts(a);
+ createFileInModuleOutput(m, "b.txt");
+ assertOutput(m, fs().file("A.class").file("b.txt"));
+
+ rebuildAll();
+ assertOutput(m, fs().file("A.class"));
+ }
+
+ private static void createFileInArtifactOutput(JpsArtifact a, final String name) {
+ createFileInOutputDir(a.getOutputPath(), name);
+ }
+
+ private static void createFileInModuleOutput(JpsModule m, final String name) {
+ File outputDirectory = JpsJavaExtensionService.getInstance().getOutputDirectory(m, false);
+ assertNotNull(outputDirectory);
+ createFileInOutputDir(outputDirectory.getAbsolutePath(), name);
+ }
+
+ private static void createFileInOutputDir(final String outputPath, final String fileName) {
+ try {
+ boolean created = new File(outputPath, fileName).createNewFile();
+ assertTrue(created);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java
new file mode 100644
index 000000000000..ef662f2d1568
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.builders.CompileScopeTestBuilder;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.IOException;
+
+import static com.intellij.util.io.TestFileSystemItem.fs;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+/**
+ * @author nik
+ */
+public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase {
+ public void testCopyChangedFile() {
+ String file1 = createFile("dir/a.txt", "aaa");
+ createFile("dir/b.txt", "bbb");
+ final JpsArtifact a = addArtifact(root().parentDirCopy(file1));
+ buildAll();
+ assertOutput(a, fs().file("a.txt", "aaa").file("b.txt", "bbb"));
+
+ buildAllAndAssertUpToDate();
+
+ change(file1, "xxx");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.txt", "dir/a.txt");
+ assertOutput(a, fs().file("a.txt", "xxx").file("b.txt", "bbb"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testRemoveDeletedFile() {
+ String file1 = createFile("dir/a.txt");
+ createFile("dir/b.txt");
+ final JpsArtifact a = addArtifact("a", root().parentDirCopy(file1));
+ buildAll();
+ assertOutput(a, fs().file("a.txt").file("b.txt"));
+
+ delete(file1);
+ buildAll();
+ assertDeleted("out/artifacts/a/a.txt");
+ assertOutput(a, fs().file("b.txt"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testPackChangedFile() {
+ String file1 = createFile("dir/a.txt", "aaa");
+ createFile("dir/b.txt", "bbb");
+ final JpsArtifact a = addArtifact(archive("a.jar").parentDirCopy(file1));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").file("a.txt", "aaa").file("b.txt", "bbb"));
+ buildAllAndAssertUpToDate();
+
+ change(file1, "xxx");
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.jar", "dir/a.txt", "dir/b.txt");
+ assertOutput(a, fs().archive("a.jar").file("a.txt", "xxx").file("b.txt", "bbb"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testRemoveDeletedFileFromArchive() {
+ String file1 = createFile("dir/a.txt");
+ createFile("dir/b.txt");
+ final JpsArtifact a = addArtifact("a", root().archive("a.jar").parentDirCopy(file1));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").file("a.txt").file("b.txt"));
+
+ delete(file1);
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/a.jar", "dir/b.txt");
+ assertOutput(a, fs().archive("a.jar").file("b.txt"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testAddFileToArchive() {
+ String file = createFile("dir/a.txt");
+ JpsArtifact a = addArtifact("a", archive("a.jar").parentDirCopy(file));
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").file("a.txt"));
+
+ createFile("dir/b.txt");
+ buildAll();
+ assertOutput(a, fs().archive("a.jar").file("a.txt").file("b.txt"));
+ assertCopied("dir/a.txt", "dir/b.txt");
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testNonExistentFileRoot() throws IOException {
+ String file = getAbsolutePath("a.txt");
+ JpsArtifact a = addArtifact(root().fileCopy(file));
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+
+ FileUtil.createIfDoesntExist(new File(file));
+ buildArtifacts(a);
+ assertOutput(a, fs().file("a.txt"));
+ buildAllAndAssertUpToDate();
+
+ delete(file);
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testNonExistentDirectoryRoot() throws IOException {
+ String dir = getAbsolutePath("d");
+ JpsArtifact a = addArtifact(root().dirCopy(dir));
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+
+ FileUtil.createIfDoesntExist(new File(dir, "a.txt"));
+ buildArtifacts(a);
+ assertOutput(a, fs().file("a.txt"));
+ buildAllAndAssertUpToDate();
+
+ delete(dir);
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testExtractFileFromNonExistentJar() throws IOException {
+ String jar = getAbsolutePath("junit.jar");
+ JpsArtifact a = addArtifact(root().extractedDir(jar, "/junit/textui/"));
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+
+ FileUtil.copy(new File(getJUnitJarPath()), new File(jar));
+ buildArtifacts(a);
+ assertOutput(a, fs().file("ResultPrinter.class")
+ .file("TestRunner.class"));
+ buildAllAndAssertUpToDate();
+
+ delete(jar);
+ buildArtifacts(a);
+ assertEmptyOutput(a);
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testOneFileInTwoArtifacts() {
+ final String file = createFile("file.txt");
+ final JpsArtifact a1 = addArtifact("a1", root().dir("dir").fileCopy(file));
+ final JpsArtifact a2 = addArtifact("a2", root().dir("dir2").fileCopy(file));
+
+ buildAll();
+ buildArtifacts(a1); assertUpToDate();
+ buildArtifacts(a2); assertUpToDate();
+ buildAllAndAssertUpToDate();
+
+ change(file);
+ buildArtifacts(a1); assertDeletedAndCopied("out/artifacts/a1/dir/file.txt", "file.txt");
+ buildArtifacts(a1); assertUpToDate();
+ buildArtifacts(a2); assertDeletedAndCopied("out/artifacts/a2/dir2/file.txt", "file.txt");
+ buildArtifacts(a2); assertUpToDate();
+ buildArtifacts(a1); assertUpToDate();
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testArtifactWithOutputPathEqualToSourcePath() {
+ String root = PathUtil.getParentPath(createFile("d/1.txt"));
+ JpsArtifact a = addArtifact(root().dirCopy(root));
+ a.setOutputPath(root);
+
+ buildArtifacts(a);
+ assertOutput(a, fs().file("1.txt"));
+ String file2 = createFile("d/2.txt");
+ buildArtifacts(a);
+ assertOutput(a, fs().file("1.txt").file("2.txt"));
+
+ a.getRootElement().addChild(JpsPackagingElementFactory.getInstance().createFileCopy(createFile("d2/3.txt"), null));
+ buildArtifacts(a);
+ assertOutput(a, fs().file("1.txt").file("2.txt").file("3.txt"));
+
+ buildAllAndAssertUpToDate();
+ assertOutput(a, fs().file("1.txt").file("2.txt").file("3.txt"));
+
+ delete(file2);
+ buildAllAndAssertUpToDate();
+ assertOutput(a, fs().file("1.txt").file("3.txt"));
+ }
+
+ public void testDeleteFileAndRebuildIncludedArtifact() {
+ String file1 = createFile("d/1.txt");
+ createFile("d/2.txt");
+ JpsArtifact included = addArtifact("i", root().parentDirCopy(file1));
+ JpsArtifact a = addArtifact(root().artifact(included));
+ makeAll();
+ assertOutput(included, fs().file("1.txt").file("2.txt"));
+ assertOutput(a, fs().file("1.txt").file("2.txt"));
+
+ delete(file1);
+ delete(included.getOutputPath());//to trigger rebuild only for 'i'
+ //doBuild(CompileScopeTestBuilder.rebuild().artifact(included)).assertSuccessful();
+ doBuild(CompileScopeTestBuilder.make().artifact(included)).assertSuccessful();
+ assertOutput(included, fs().file("2.txt"));
+ assertOutput(a, fs().file("1.txt").file("2.txt"));
+
+ makeAll();
+ assertOutput(a, fs().file("2.txt"));
+ }
+
+ public void testMoveClassFromOneModuleToAnother() {
+ String file = createFile("src1/A.java", "class A{}");
+ JpsModule m1 = addModule("m1", PathUtil.getParentPath(file));
+ JpsModule m2 = addModule("m2", PathUtil.getParentPath(createFile("src2/B.java", "class B{}")));
+ JpsArtifact a = addArtifact(root().module(m1).module(m2));
+ buildAll();
+ assertOutput(a, fs().file("A.class").file("B.class"));
+
+ delete(file);
+ createFile("src2/A.java", "class A{}");
+ buildAll();
+ assertOutput(a, fs().file("A.class").file("B.class"));
+ assertDeletedAndCopied(new String[] {"out/artifacts/a/A.class", "out/production/m1/A.class"}, "out/production/m2/A.class");
+ buildAllAndAssertUpToDate();
+ }
+
+ //IDEADEV-40714
+ public void testOverwriteFileInArchive() {
+ final String file1 = createFile("a/a.txt", "a");
+ final String file2 = createFile("b/a.txt", "b");
+ addArtifact(root()
+ .archive("x.jar")
+ .fileCopy(file1)
+ .fileCopy(file2));
+ buildAll();
+ change(file1);
+ buildAll();
+ assertDeletedAndCopied("out/artifacts/a/x.jar", "a/a.txt");
+ }
+
+ public void testRenameFile() throws Exception {
+ final String file = createFile("a/a.txt");
+ final JpsArtifact a = addArtifact(root().parentDirCopy(file));
+ buildAll();
+
+ assertOutput(a, fs().file("a.txt"));
+ rename(file, "b.txt");
+ buildAll();
+ assertOutput(a, fs().file("b.txt"));
+ }
+
+ //IDEADEV-25840
+ public void testUpdateFileIfCaseOfLetterInNameChanged() throws Exception {
+ final String file = createFile("a/a.txt");
+ final JpsArtifact a = addArtifact("a", root().parentDirCopy(file));
+ buildAll();
+
+ assertOutput(a, fs().file("a.txt"));
+ rename(file, "A.txt");
+ buildAll();
+ assertOutput(a, fs().file("A.txt"));
+ }
+
+ //IDEADEV-41556
+ public void testDeleteFilesFromSelectedArtifactsOnly() throws Exception {
+ final String file = createFile("a/a.txt");
+ final JpsArtifact a1 = addArtifact("a1", root().parentDirCopy(file));
+ final JpsArtifact a2 = addArtifact("a2", root().parentDirCopy(file));
+
+ buildAll();
+ assertOutput(a1, fs().file("a.txt"));
+ assertOutput(a2, fs().file("a.txt"));
+
+ delete(file);
+ buildArtifacts(a1); assertDeleted("out/artifacts/a1/a.txt");
+ assertEmptyOutput(a1);
+ assertOutput(a2, fs().file("a.txt"));
+
+ buildArtifacts(a2); assertDeleted("out/artifacts/a2/a.txt");
+ assertEmptyOutput(a1);
+ assertEmptyOutput(a2);
+ }
+
+ //IDEA-51910
+ public void testTwoArtifactsWithSameOutput() throws Exception {
+ final String res1 = PathUtil.getParentPath(createFile("res1/a.txt", "1"));
+ final String res2 = PathUtil.getParentPath(createFile("res2/a.txt", "2"));
+ final JpsArtifact a1 = addArtifact("a1", root().dirCopy(res1));
+ final JpsArtifact a2 = addArtifact("a2", root().dirCopy(res2));
+ a2.setOutputPath(a1.getOutputPath());
+ assertEquals(a1.getOutputPath(), a2.getOutputPath());
+
+ buildArtifacts(a1);
+ assertOutput(a1, fs().file("a.txt", "1"));
+ assertOutput(a2, fs().file("a.txt", "1"));
+ buildArtifacts(a1); assertUpToDate();
+
+ buildArtifacts(a2);
+ assertOutput(a2, fs().file("a.txt", "2"));
+ }
+
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java
new file mode 100644
index 000000000000..09198eb47d54
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.*;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public class LayoutElementTestUtil {
+ public static LayoutElementCreator root() {
+ return new LayoutElementCreator(JpsPackagingElementFactory.getInstance().createArtifactRoot(), null);
+ }
+
+ public static LayoutElementCreator archive(String name) {
+ return new LayoutElementCreator(JpsPackagingElementFactory.getInstance().createArchive(name), null);
+ }
+
+ public static void addArtifactToLayout(JpsArtifact main, JpsArtifact included) {
+ main.getRootElement().addChild(JpsPackagingElementFactory.getInstance().createArtifactOutput(included.createReference()));
+ }
+
+ public static class LayoutElementCreator {
+ private JpsPackagingElementFactory myFactory;
+ private JpsCompositePackagingElement myElement;
+ private LayoutElementCreator myParent;
+
+ public LayoutElementCreator(JpsCompositePackagingElement element, LayoutElementCreator parent) {
+ myElement = element;
+ myParent = parent;
+ myFactory = JpsPackagingElementFactory.getInstance();
+ }
+
+ public LayoutElementCreator dir(String name) {
+ JpsDirectoryPackagingElement dir = myFactory.createDirectory(name);
+ myElement.addChild(dir);
+ return new LayoutElementCreator(dir, this);
+ }
+
+ public LayoutElementCreator archive(String name) {
+ JpsArchivePackagingElement archive = myFactory.createArchive(name);
+ myElement.addChild(archive);
+ return new LayoutElementCreator(archive, this);
+ }
+
+ public LayoutElementCreator fileCopy(String filePath) {
+ return fileCopy(filePath, null);
+ }
+
+ public LayoutElementCreator fileCopy(String filePath, @Nullable String outputFileName) {
+ return element(myFactory.createFileCopy(filePath, outputFileName));
+ }
+
+ public LayoutElementCreator dirCopy(String dirPath) {
+ return element(myFactory.createDirectoryCopy(dirPath));
+ }
+
+ public LayoutElementCreator parentDirCopy(String filePath) {
+ return dirCopy(PathUtil.getParentPath(filePath));
+ }
+
+ public LayoutElementCreator module(JpsModule module) {
+ return element(JpsJavaExtensionService.getInstance().createProductionModuleOutput(module.createReference()));
+ }
+
+ public LayoutElementCreator element(JpsPackagingElement element) {
+ myElement.addChild(element);
+ return this;
+ }
+
+ public LayoutElementCreator lib(JpsLibrary library) {
+ return element(myFactory.createLibraryElement(library.createReference()));
+ }
+
+ public LayoutElementCreator extractedDir(String jarPath, String pathInJar) {
+ return element(myFactory.createExtractedDirectory(jarPath, pathInJar));
+ }
+
+ public LayoutElementCreator artifact(JpsArtifact included) {
+ return element(myFactory.createArtifactOutput(included.createReference()));
+ }
+
+ public LayoutElementCreator end() {
+ return myParent;
+ }
+
+ public JpsCompositePackagingElement buildElement() {
+ if (myParent != null) {
+ return myParent.buildElement();
+ }
+ return myElement;
+ }
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java
new file mode 100644
index 000000000000..f998e20eb3fa
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.util.PathUtil;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory;
+
+import static com.intellij.util.io.TestFileSystemBuilder.fs;
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+/**
+ * @author nik
+ */
+public class RebuildArtifactOnConfigurationChangeTest extends ArtifactBuilderTestCase {
+ public void testAddRoot() {
+ String dir1 = PathUtil.getParentPath(createFile("dir1/a.txt", "a"));
+ String dir2 = PathUtil.getParentPath(createFile("dir2/b.txt", "b"));
+ JpsArtifact a = addArtifact(root().dirCopy(dir1));
+ buildAll();
+ assertOutput(a, fs().file("a.txt", "a"));
+
+ a.getRootElement().addChild(JpsPackagingElementFactory.getInstance().createDirectoryCopy(dir2));
+ buildAll();
+ assertOutput(a, fs().file("a.txt", "a").file("b.txt", "b"));
+ assertDeletedAndCopied("out/artifacts/a/a.txt", "dir1/a.txt", "dir2/b.txt");
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testRemoveRoot() {
+ String file1 = createFile("dir1/a.txt", "a");
+ String file2 = createFile("dir2/b.txt", "b");
+ JpsArtifact a = addArtifact(root().parentDirCopy(file1).parentDirCopy(file2));
+ buildAll();
+ assertOutput(a, fs().file("a.txt", "a").file("b.txt", "b"));
+
+ a.getRootElement().removeChild(a.getRootElement().getChildren().get(0));
+ buildAll();
+ assertOutput(a, fs().file("b.txt", "b"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testChangeOutput() {
+ String file = createFile("dir/a.txt");
+ JpsArtifact a = addArtifact(root().parentDirCopy(file));
+ buildAll();
+ String oldOutput = a.getOutputPath();
+ assertNotNull(oldOutput);
+ assertOutput(oldOutput, fs().file("a.txt"));
+
+ String newOutput = PathUtil.getParentPath(oldOutput) + "/a2";
+ a.setOutputPath(newOutput);
+ buildAll();
+ assertOutput(newOutput, fs().file("a.txt"));
+ assertOutput(oldOutput, fs());
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testChangeConfiguration() {
+ String file = createFile("d/a.txt", "a");
+ JpsArtifact a = addArtifact(root().parentDirCopy(file));
+ buildAll();
+ assertOutput(a, fs().file("a.txt", "a"));
+
+ a.setRootElement(root().dir("dir").parentDirCopy(file).buildElement());
+ buildAll();
+ assertOutput(a, fs().dir("dir").file("a.txt", "a"));
+ buildAllAndAssertUpToDate();
+ }
+
+ public void testAddRootChangingRootIndices() {
+ String file1 = createFile("d1/a/b/1.txt");
+ String file2 = createFile("d2/x/y/2.txt");
+ JpsArtifact a = addArtifact(root().fileCopy(file1).fileCopy(file2));
+ buildAll();
+ assertOutput(a, fs().file("1.txt").file("2.txt"));
+
+ JpsCompositePackagingElement root = a.getRootElement();
+ assertEquals(2, root.getChildren().size());
+ JpsPackagingElement last = root.getChildren().get(1);
+ root.removeChild(last);
+ String file3 = createFile("d3/1/2/3.txt");
+ root.addChild(JpsPackagingElementFactory.getInstance().createFileCopy(file3, null));
+ root.addChild(last);
+
+ buildAll();
+ assertOutput(a, fs().file("1.txt").file("2.txt").file("3.txt"));
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/indices/ModuleExcludeIndexTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/indices/ModuleExcludeIndexTest.java
new file mode 100644
index 000000000000..8cfc000f45f5
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/indices/ModuleExcludeIndexTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.indices;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.jps.indices.impl.ModuleExcludeIndexImpl;
+import org.jetbrains.jps.model.JpsJavaModelTestCase;
+import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public class ModuleExcludeIndexTest extends JpsJavaModelTestCase {
+ private File myRoot;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myRoot = FileUtil.createTempDirectory("excludes", null);
+ }
+
+ public void testExcludeProjectOutput() throws IOException {
+ File out = new File(myRoot, "out");
+ getJavaService().getOrCreateProjectExtension(myProject).setOutputUrl(JpsPathUtil.pathToUrl(out.getAbsolutePath()));
+ JpsModule module1 = addModule();
+ getJavaService().getOrCreateModuleExtension(module1).setInheritOutput(true);
+ JpsModule module2 = addModule();
+ module2.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(out.getAbsolutePath()));
+ getJavaService().getOrCreateModuleExtension(module2).setInheritOutput(true);
+
+ assertNotExcluded(myRoot);
+ assertExcluded(out);
+ assertEmpty(getModuleExcludes(module1));
+ assertSameElements(getModuleExcludes(module2), out);
+ }
+
+ public void testExcludeModuleOutput() {
+ File out = new File(myRoot, "out");
+ JpsModule module = addModule();
+ JpsJavaModuleExtension extension = getJavaService().getOrCreateModuleExtension(module);
+ extension.setExcludeOutput(true);
+ extension.setOutputUrl(JpsPathUtil.pathToUrl(out.getAbsolutePath()));
+
+ assertNotExcluded(myRoot);
+ assertExcluded(out);
+ assertSameElements(getModuleExcludes(module), out);
+
+ extension.setExcludeOutput(false);
+ assertNotExcluded(out);
+ assertEmpty(getModuleExcludes(module));
+ }
+
+ public void testExcludeExcludedFolder() {
+ File exc = new File(myRoot, "exc");
+ JpsModule module = addModule();
+ module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(exc.getAbsolutePath()));
+
+ assertNotExcluded(myRoot);
+ assertExcluded(exc);
+ assertSameElements(getModuleExcludes(module), exc);
+ }
+
+ private Collection<File> getModuleExcludes(JpsModule module) {
+ return new ModuleExcludeIndexImpl(myModel).getModuleExcludes(module);
+ }
+
+ private void assertExcluded(File file) {
+ assertTrue(new ModuleExcludeIndexImpl(myModel).isExcluded(file));
+ }
+
+ private void assertNotExcluded(File file) {
+ assertFalse(new ModuleExcludeIndexImpl(myModel).isExcluded(file));
+ }
+}
diff --git a/jps/lib/gant-1.9.5_groovy-1.7.10.jar b/jps/lib/gant-1.9.5_groovy-1.7.10.jar
new file mode 100644
index 000000000000..c3b9c9c7faa6
--- /dev/null
+++ b/jps/lib/gant-1.9.5_groovy-1.7.10.jar
Binary files differ
diff --git a/jps/lib/optimizedFileManager.jar b/jps/lib/optimizedFileManager.jar
new file mode 100644
index 000000000000..d744fd8cff84
--- /dev/null
+++ b/jps/lib/optimizedFileManager.jar
Binary files differ
diff --git a/jps/model-api/jps-model-api.iml b/jps/model-api/jps-model-api.iml
new file mode 100644
index 000000000000..7e88b0067116
--- /dev/null
+++ b/jps/model-api/jps-model-api.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="annotations" />
+ <orderEntry type="module" module-name="util-rt" />
+ </component>
+</module>
+
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsCompositeElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsCompositeElement.java
new file mode 100644
index 000000000000..24f057e25dfa
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsCompositeElement.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsCompositeElement extends JpsElement {
+ @NotNull
+ JpsElementContainer getContainer();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsDummyElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsDummyElement.java
new file mode 100644
index 000000000000..89fb27a30d80
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsDummyElement.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+/**
+ * @author nik
+ */
+public interface JpsDummyElement extends JpsElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElement.java
new file mode 100644
index 000000000000..2ec58f589793
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElement.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsElement {
+ @NotNull
+ BulkModificationSupport<?> getBulkModificationSupport();
+
+ interface BulkModificationSupport<E extends JpsElement> extends JpsElement {
+ @NotNull
+ E createCopy();
+
+ void applyChanges(@NotNull E modified);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementChildRole.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementChildRole.java
new file mode 100644
index 000000000000..0f417e2b9a64
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementChildRole.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class JpsElementChildRole<E extends JpsElement> {
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull E element) {
+ }
+
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull E element) {
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementCollection.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementCollection.java
new file mode 100644
index 000000000000..59ca593661df
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementCollection.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsElementCollection<E extends JpsElement> extends JpsElement {
+ List<E> getElements();
+
+ @NotNull
+ E addChild(@NotNull JpsElementCreator<E> creator);
+
+ <X extends E> X addChild(X element);
+
+ void removeChild(@NotNull E element);
+
+ void removeAllChildren();
+
+ <X extends JpsTypedElement<P>, P extends JpsElement>
+ Iterable<X> getElementsOfType(@NotNull JpsElementType<P> type);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementContainer.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementContainer.java
new file mode 100644
index 000000000000..231a6473d486
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementContainer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsElementContainer {
+ <T extends JpsElement>
+ T getChild(@NotNull JpsElementChildRole<T> role);
+
+ @NotNull
+ <T extends JpsElement, K extends JpsElementChildRole<T> &JpsElementCreator<T>>
+ T setChild(@NotNull K role);
+
+ @NotNull
+ <T extends JpsElement, K extends JpsElementChildRole<T> &JpsElementCreator<T>>
+ T getOrSetChild(@NotNull K role);
+
+ @NotNull
+ <T extends JpsElement, P, K extends JpsElementChildRole<T> &JpsElementParameterizedCreator<T, P>>
+ T setChild(@NotNull K role, @NotNull P param);
+
+ <T extends JpsElement>
+ T setChild(JpsElementChildRole<T> role, T child);
+
+ <T extends JpsElement>
+ void removeChild(@NotNull JpsElementChildRole<T> role);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementCreator.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementCreator.java
new file mode 100644
index 000000000000..bc3c436dfa7f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementCreator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsElementCreator<E extends JpsElement> {
+ @NotNull
+ E create();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementFactory.java
new file mode 100644
index 000000000000..d4f046194d15
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementFactory.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementFactory {
+ public static JpsElementFactory getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsElementFactory.class);
+ }
+
+ public abstract JpsModel createModel();
+
+ public abstract <P extends JpsElement> JpsModule createModule(@NotNull String name, @NotNull JpsModuleType<P> type, @NotNull P properties);
+
+ public abstract <P extends JpsElement> JpsTypedLibrary<P> createLibrary(@NotNull String name, @NotNull JpsLibraryType<P> type, @NotNull P properties);
+
+ public abstract <P extends JpsElement> JpsTypedLibrary<JpsSdk<P>> createSdk(@NotNull String name, @Nullable String homePath, @Nullable String versionString,
+ @NotNull JpsSdkType<P> type, @NotNull P properties);
+
+ @NotNull
+ public abstract JpsModuleReference createModuleReference(@NotNull String moduleName);
+
+ @NotNull
+ public abstract JpsLibraryReference createLibraryReference(@NotNull String libraryName,
+ @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference);
+
+ @NotNull
+ public abstract <P extends JpsElement> JpsSdkReference<P> createSdkReference(@NotNull String sdkName,
+ @NotNull JpsSdkType<P> sdkType);
+
+ @NotNull
+ public abstract JpsElementReference<JpsProject> createProjectReference();
+
+ @NotNull
+ public abstract JpsElementReference<JpsGlobal> createGlobalReference();
+
+ @NotNull
+ public abstract JpsDummyElement createDummyElement();
+
+ @NotNull
+ public abstract <D> JpsSimpleElement<D> createSimpleElement(@NotNull D data);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementParameterizedCreator.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementParameterizedCreator.java
new file mode 100644
index 000000000000..72b46cb85a5f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementParameterizedCreator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsElementParameterizedCreator<E extends JpsElement, P> {
+ @NotNull
+ E create(@NotNull P param);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementReference.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementReference.java
new file mode 100644
index 000000000000..a041969a50b8
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementReference.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public interface JpsElementReference<T extends JpsElement> extends JpsElement {
+ @Nullable
+ T resolve();
+
+ JpsElementReference<T> asExternal(@NotNull JpsModel model);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementType.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementType.java
new file mode 100644
index 000000000000..1adee500560a
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementType<P extends JpsElement> {
+ private final JpsElementChildRole<P> myPropertiesRole = new JpsElementChildRole<P>();
+
+ public final JpsElementChildRole<P> getPropertiesRole() {
+ return myPropertiesRole;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsElementTypeWithDefaultProperties.java b/jps/model-api/src/org/jetbrains/jps/model/JpsElementTypeWithDefaultProperties.java
new file mode 100644
index 000000000000..47d67ee21b04
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsElementTypeWithDefaultProperties.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsElementTypeWithDefaultProperties<P> {
+ @NotNull
+ P createDefaultProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingConfigurationService.java b/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingConfigurationService.java
new file mode 100644
index 000000000000..e36e98560f1e
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingConfigurationService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public abstract class JpsEncodingConfigurationService {
+ public static JpsEncodingConfigurationService getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsEncodingConfigurationService.class);
+ }
+
+ @Nullable
+ public abstract String getGlobalEncoding(@NotNull JpsGlobal global);
+
+ public abstract void setGlobalEncoding(@NotNull JpsGlobal global, @Nullable String encoding);
+
+ @Nullable
+ public abstract String getProjectEncoding(@NotNull JpsModel model);
+
+ @Nullable
+ public abstract JpsEncodingProjectConfiguration getEncodingConfiguration(@NotNull JpsProject project);
+
+ @NotNull
+ public abstract JpsEncodingProjectConfiguration setEncodingConfiguration(@NotNull JpsProject project, @Nullable String projectEncoding,
+ @NotNull Map<String, String> urlToEncoding);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingProjectConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingProjectConfiguration.java
new file mode 100644
index 000000000000..95cba000a101
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsEncodingProjectConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public interface JpsEncodingProjectConfiguration extends JpsElement {
+ @Nullable
+ String getEncoding(@NotNull File file);
+
+ @Nullable
+ String getProjectEncoding();
+
+ @NotNull
+ Map<String, String> getUrlToEncoding();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsEventDispatcher.java b/jps/model-api/src/org/jetbrains/jps/model/JpsEventDispatcher.java
new file mode 100644
index 000000000000..fe74a3a720b3
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsEventDispatcher.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsEventDispatcher {
+ @NotNull
+ <T extends EventListener> T getPublisher(Class<T> listenerClass);
+
+ void fireElementRenamed(@NotNull JpsNamedElement element, @NotNull String oldName, @NotNull String newName);
+
+ void fireElementChanged(@NotNull JpsElement element);
+
+ <T extends JpsElement>
+ void fireElementAdded(@NotNull T element, @NotNull JpsElementChildRole<T> role);
+
+ <T extends JpsElement>
+ void fireElementRemoved(@NotNull T element, @NotNull JpsElementChildRole<T> role);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsFileTypesConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/JpsFileTypesConfiguration.java
new file mode 100644
index 000000000000..e7732353e9d4
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsFileTypesConfiguration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsFileTypesConfiguration extends JpsElement {
+ String getIgnoredPatternString();
+
+ void setIgnoredPatternString(@NotNull String ignoredPatternString);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsGlobal.java b/jps/model-api/src/org/jetbrains/jps/model/JpsGlobal.java
new file mode 100644
index 000000000000..2b92580e862f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsGlobal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.*;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+/**
+ * @author nik
+ */
+public interface JpsGlobal extends JpsCompositeElement, JpsReferenceableElement<JpsGlobal> {
+ @NotNull
+ <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull LibraryType libraryType, final @NotNull String name);
+
+ <P extends JpsElement, SdkType extends JpsSdkType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsTypedLibrary<JpsSdk<P>> addSdk(@NotNull String name, @Nullable String homePath, @Nullable String versionString, @NotNull SdkType type);
+
+ <P extends JpsElement>
+ JpsTypedLibrary<JpsSdk<P>> addSdk(@NotNull String name, @Nullable String homePath, @Nullable String versionString,
+ @NotNull JpsSdkType<P> type, @NotNull P properties);
+
+ @NotNull
+ JpsLibraryCollection getLibraryCollection();
+
+ @NotNull
+ JpsFileTypesConfiguration getFileTypesConfiguration();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsModel.java b/jps/model-api/src/org/jetbrains/jps/model/JpsModel.java
new file mode 100644
index 000000000000..469bab8e865e
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsModel.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsModel {
+ @NotNull
+ JpsProject getProject();
+
+ @NotNull
+ JpsGlobal getGlobal();
+
+ @NotNull
+ JpsModel createModifiableModel(@NotNull JpsEventDispatcher eventDispatcher);
+
+ void registerExternalReference(@NotNull JpsElementReference<?> reference);
+
+ void commit();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElement.java
new file mode 100644
index 000000000000..b08b12aa6f2e
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElement.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsNamedElement extends JpsElement {
+ @NotNull
+ String getName();
+
+ void setName(@NotNull String name);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsProject.java b/jps/model-api/src/org/jetbrains/jps/model/JpsProject.java
new file mode 100644
index 000000000000..0b2e90533b24
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsProject.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryCollection;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.model.module.JpsSdkReferencesTable;
+import org.jetbrains.jps.model.module.JpsTypedModule;
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfigurationType;
+import org.jetbrains.jps.model.runConfiguration.JpsTypedRunConfiguration;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsProject extends JpsCompositeElement, JpsReferenceableElement<JpsProject> {
+
+ @NotNull
+ <P extends JpsElement, ModuleType extends JpsModuleType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsModule addModule(@NotNull String name, @NotNull ModuleType moduleType);
+
+ void addModule(@NotNull JpsModule module);
+
+ @NotNull
+ List<JpsModule> getModules();
+
+ @NotNull
+ <P extends JpsElement>
+ Iterable<JpsTypedModule<P>> getModules(JpsModuleType<P> type);
+
+ @NotNull
+ <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull String name, @NotNull LibraryType libraryType);
+
+ @NotNull
+ JpsLibraryCollection getLibraryCollection();
+
+ @NotNull
+ JpsSdkReferencesTable getSdkReferencesTable();
+
+ @NotNull
+ <P extends JpsElement>
+ Iterable<JpsTypedRunConfiguration<P>> getRunConfigurations(JpsRunConfigurationType<P> type);
+
+ @NotNull
+ <P extends JpsElement>
+ JpsTypedRunConfiguration<P> addRunConfiguration(@NotNull String name, @NotNull JpsRunConfigurationType<P> type, @NotNull P properties);
+
+ @NotNull String getName();
+
+ void setName(@NotNull String name);
+
+ @NotNull
+ JpsModel getModel();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsReferenceableElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsReferenceableElement.java
new file mode 100644
index 000000000000..c80481d08909
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsReferenceableElement.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsReferenceableElement<E extends JpsElement> {
+ @NotNull
+ JpsElementReference<E> createReference();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsSimpleElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsSimpleElement.java
new file mode 100644
index 000000000000..1c9be6279341
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsSimpleElement.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsSimpleElement<D> extends JpsElement {
+ @NotNull
+ D getData();
+
+ void setData(@NotNull D data);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsTypedElement.java b/jps/model-api/src/org/jetbrains/jps/model/JpsTypedElement.java
new file mode 100644
index 000000000000..4302d3b227e9
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsTypedElement.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsTypedElement<P extends JpsElement> extends JpsElement {
+ JpsElementType<?> getType();
+
+ @NotNull
+ P getProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsUrlList.java b/jps/model-api/src/org/jetbrains/jps/model/JpsUrlList.java
new file mode 100644
index 000000000000..806cdfeac59b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsUrlList.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsUrlList extends JpsElement {
+ @NotNull
+ List<String> getUrls();
+
+ void addUrl(@NotNull String url);
+
+ void removeUrl(@NotNull String url);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsUrlListChangeListener.java b/jps/model-api/src/org/jetbrains/jps/model/JpsUrlListChangeListener.java
new file mode 100644
index 000000000000..d980c5f65d6a
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/JpsUrlListChangeListener.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface JpsUrlListChangeListener<T extends JpsElement> {
+ void urlAdded(@NotNull T element, @NotNull String url);
+
+ void urlRemoved(@NotNull T element, @NotNull String url);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java
new file mode 100644
index 000000000000..3b66462f9d8a
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.jps.model.JpsDummyElement;
+
+/**
+ * @author nik
+ */
+public class DirectoryArtifactType extends JpsArtifactType<JpsDummyElement> {
+ public static final DirectoryArtifactType INSTANCE = new DirectoryArtifactType();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java
new file mode 100644
index 000000000000..c0306a9f447b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.jps.model.JpsDummyElement;
+
+/**
+ * @author nik
+ */
+public class JarArtifactType extends JpsArtifactType<JpsDummyElement> {
+ public static final JarArtifactType INSTANCE = new JarArtifactType();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java
new file mode 100644
index 000000000000..d7c6ab978995
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsNamedElement;
+import org.jetbrains.jps.model.JpsReferenceableElement;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+
+/**
+ * @author nik
+ */
+public interface JpsArtifact extends JpsNamedElement, JpsReferenceableElement<JpsArtifact>, JpsCompositeElement {
+ @NotNull
+ JpsArtifactType<?> getArtifactType();
+
+ @Nullable
+ String getOutputPath();
+
+ void setOutputPath(@Nullable String outputPath);
+
+ @Nullable
+ String getOutputFilePath();
+
+ @NotNull
+ JpsCompositePackagingElement getRootElement();
+
+ void setRootElement(@NotNull JpsCompositePackagingElement rootElement);
+
+ boolean isBuildOnMake();
+
+ @NotNull
+ @Override
+ JpsArtifactReference createReference();
+
+ void setBuildOnMake(boolean buildOnMake);
+
+ JpsElement getProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java
new file mode 100644
index 000000000000..b47aa275e219
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public interface JpsArtifactReference extends JpsElementReference<JpsArtifact> {
+ @NotNull
+ String getArtifactName();
+
+ @Override
+ JpsArtifactReference asExternal(@NotNull JpsModel model);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java
new file mode 100644
index 000000000000..2c87c62b2d51
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsArtifactService {
+
+ public static JpsArtifactService getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsArtifactService.class);
+ }
+
+ public abstract <P extends JpsElement> JpsArtifact createArtifact(@NotNull String name, @NotNull JpsCompositePackagingElement rootElement,
+ @NotNull JpsArtifactType<P> type, @NotNull P properties);
+
+ public abstract List<JpsArtifact> getArtifacts(@NotNull JpsProject project);
+
+ public abstract List<JpsArtifact> getSortedArtifacts(@NotNull JpsProject project);
+
+ public abstract <P extends JpsElement> JpsArtifact addArtifact(@NotNull JpsProject project, @NotNull String name,
+ @NotNull JpsCompositePackagingElement rootElement,
+ @NotNull JpsArtifactType<P> type, @NotNull P properties);
+
+ public abstract JpsArtifactReference createReference(@NotNull String artifactName);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java
new file mode 100644
index 000000000000..a4a6c312438d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+
+/**
+ * @author nik
+ */
+public abstract class JpsArtifactType<P extends JpsElement> extends JpsElementType<P> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java
new file mode 100644
index 000000000000..a8c692b60360
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsArchivePackagingElement extends JpsCompositePackagingElement {
+ String getArchiveName();
+
+ void setArchiveName(String directoryName);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java
new file mode 100644
index 000000000000..65faa7cbfb74
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+
+/**
+ * @author nik
+ */
+public interface JpsArtifactOutputPackagingElement extends JpsComplexPackagingElement {
+ @NotNull
+ JpsArtifactReference getArtifactReference();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java
new file mode 100644
index 000000000000..9c3180a4ef24
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsArtifactRootElement extends JpsCompositePackagingElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java
new file mode 100644
index 000000000000..1be7830349d5
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsComplexPackagingElement extends JpsPackagingElement {
+ List<JpsPackagingElement> getSubstitution();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java
new file mode 100644
index 000000000000..586a80516b82
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsCompositePackagingElement extends JpsPackagingElement {
+ @NotNull
+ List<JpsPackagingElement> getChildren();
+
+ <E extends JpsPackagingElement> E addChild(@NotNull E child);
+
+ void removeChild(@NotNull JpsPackagingElement child);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java
new file mode 100644
index 000000000000..f6c3db6d5421
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsDirectoryCopyPackagingElement extends JpsPackagingElement {
+ String getDirectoryPath();
+
+ void setDirectoryPath(String path);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java
new file mode 100644
index 000000000000..d7c5afdd63ed
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsDirectoryPackagingElement extends JpsCompositePackagingElement {
+
+ String getDirectoryName();
+
+ void setDirectoryName(String directoryName);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java
new file mode 100644
index 000000000000..2d2a6ec9898b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsExtractedDirectoryPackagingElement extends JpsPackagingElement {
+ String getFilePath();
+
+ void setFilePath(String path);
+
+ String getPathInJar();
+
+ void setPathInJar(String pathInJar);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java
new file mode 100644
index 000000000000..b98f970e2bfb
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+/**
+ * @author nik
+ */
+public interface JpsFileCopyPackagingElement extends JpsPackagingElement {
+
+ String getFilePath();
+
+ void setFilePath(String filePath);
+
+ String getRenamedOutputFileName();
+
+ void setRenamedOutputFileName(String renamedOutputFileName);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java
new file mode 100644
index 000000000000..1f50f533589b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryFilesPackagingElement extends JpsPackagingElement {
+ @NotNull
+ JpsLibraryReference getLibraryReference();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java
new file mode 100644
index 000000000000..3a49d95fd38d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleOutputPackagingElement extends JpsPackagingElement {
+ @NotNull
+ JpsModuleReference getModuleReference();
+
+ @Nullable
+ String getOutputUrl();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java
new file mode 100644
index 000000000000..ed40b81a3502
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsPackagingElement extends JpsElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java
new file mode 100644
index 000000000000..f9268c405051
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author nik
+ */
+public abstract class JpsPackagingElementFactory {
+ public abstract JpsCompositePackagingElement getOrCreateDirectory(@NotNull JpsCompositePackagingElement root, @NotNull String path);
+
+ public abstract JpsCompositePackagingElement getOrCreateArchive(@NotNull JpsCompositePackagingElement root, @NotNull String path);
+
+ public static JpsPackagingElementFactory getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsPackagingElementFactory.class);
+ }
+
+ @NotNull
+ public abstract JpsDirectoryCopyPackagingElement createDirectoryCopy(@NotNull String directoryPath);
+
+ public abstract JpsPackagingElement createParentDirectories(String path, JpsPackagingElement element);
+
+ @NotNull
+ public abstract JpsFileCopyPackagingElement createFileCopy(@NotNull String filePath, @Nullable String outputFileName);
+
+ @NotNull
+ public abstract JpsExtractedDirectoryPackagingElement createExtractedDirectory(@NotNull String jarPath, @NotNull String pathInJar);
+
+ @NotNull
+ public abstract JpsDirectoryPackagingElement createDirectory(@NotNull String directoryName);
+
+ @NotNull
+ public abstract JpsArchivePackagingElement createArchive(@NotNull String archiveName);
+
+ @NotNull
+ public abstract JpsArtifactRootElement createArtifactRoot();
+
+ @NotNull
+ public abstract JpsLibraryFilesPackagingElement createLibraryElement(@NotNull JpsLibraryReference reference);
+
+ @NotNull
+ public abstract JpsArtifactOutputPackagingElement createArtifactOutput(@NotNull JpsArtifactReference reference);
+
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/ex/JpsComplexPackagingElementBase.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/ex/JpsComplexPackagingElementBase.java
new file mode 100644
index 000000000000..56e79293ca67
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/ex/JpsComplexPackagingElementBase.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.elements.ex;
+
+import org.jetbrains.jps.model.artifact.elements.JpsComplexPackagingElement;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+
+/**
+ * @author nik
+ */
+public abstract class JpsComplexPackagingElementBase<Self extends JpsComplexPackagingElementBase<Self>> extends JpsCompositeElementBase<Self> implements
+ JpsComplexPackagingElement {
+ protected JpsComplexPackagingElementBase() {
+ }
+
+ protected JpsComplexPackagingElementBase(JpsComplexPackagingElementBase<Self> original) {
+ super(original);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsCompositeElementBase.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsCompositeElementBase.java
new file mode 100644
index 000000000000..08ff13becf4b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsCompositeElementBase.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementContainer;
+
+/**
+ * @author nik
+ */
+public abstract class JpsCompositeElementBase<Self extends JpsCompositeElementBase<Self>> extends JpsElementBase<Self> implements JpsCompositeElement {
+ protected final JpsElementContainerEx myContainer;
+
+ protected JpsCompositeElementBase() {
+ myContainer = JpsExElementFactory.getInstance().createContainer(this);
+ }
+
+ protected JpsCompositeElementBase(JpsCompositeElementBase<Self> original) {
+ myContainer = JpsExElementFactory.getInstance().createContainerCopy(original.myContainer, this);
+ }
+
+ public void applyChanges(@NotNull Self modified) {
+ myContainer.applyChanges(modified.myContainer);
+ }
+
+ @Override
+ @NotNull
+ public JpsElementContainer getContainer() {
+ return myContainer;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementBase.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementBase.java
new file mode 100644
index 000000000000..d0379bd07462
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementBase.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementBase<Self extends JpsElementBase<Self>> implements JpsElement, JpsElement.BulkModificationSupport<Self> {
+ protected JpsElementBase myParent;
+
+ protected JpsElementBase() {
+ }
+
+ public void setParent(@Nullable JpsElementBase<?> parent) {
+ if (myParent != null && parent != null) {
+ throw new AssertionError("Parent for " + this + " is already set: " + myParent);
+ }
+ myParent = parent;
+ }
+
+ protected void fireElementChanged() {
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementChanged(this);
+ }
+ }
+
+ protected static void setParent(@NotNull JpsElement element, @Nullable JpsElementBase<?> parent) {
+ ((JpsElementBase<?>)element).setParent(parent);
+ }
+
+ @Nullable
+ protected JpsEventDispatcher getEventDispatcher() {
+ if (myParent != null) {
+ return myParent.getEventDispatcher();
+ }
+ return null;
+ }
+
+ @Nullable
+ protected JpsModel getModel() {
+ if (myParent != null) {
+ return myParent.getModel();
+ }
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public BulkModificationSupport<?> getBulkModificationSupport() {
+ return this;
+ }
+
+ @NotNull
+ public abstract Self createCopy();
+
+ public abstract void applyChanges(@NotNull Self modified);
+
+ public JpsElementBase getParent() {
+ return myParent;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementChildRoleBase.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementChildRoleBase.java
new file mode 100644
index 000000000000..17036f1e9f80
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementChildRoleBase.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+
+/**
+ * @author nik
+ */
+public class JpsElementChildRoleBase<E extends JpsElement> extends JpsElementChildRole<E> {
+ private String myDebugName;
+
+ protected JpsElementChildRoleBase(String debugName) {
+ myDebugName = debugName;
+ }
+
+ @Override
+ public String toString() {
+ return myDebugName;
+ }
+
+ public static <E extends JpsElement> JpsElementChildRoleBase<E> create(String debugName) {
+ return new JpsElementChildRoleBase<E>(debugName);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementCollectionRole.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementCollectionRole.java
new file mode 100644
index 000000000000..cecee04a256f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementCollectionRole.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+
+/**
+ * @author nik
+ */
+public class JpsElementCollectionRole<E extends JpsElement> extends JpsElementChildRoleBase<JpsElementCollection<E>>
+ implements JpsElementCreator<JpsElementCollection<E>> {
+ private final JpsElementChildRole<E> myChildRole;
+
+ private JpsElementCollectionRole(@NotNull JpsElementChildRole<E> role) {
+ super("collection of " + role);
+ myChildRole = role;
+ }
+
+ @NotNull
+ @Override
+ public JpsElementCollection<E> create() {
+ return JpsExElementFactory.getInstance().createCollection(myChildRole);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ return myChildRole.equals(((JpsElementCollectionRole)o).myChildRole);
+ }
+
+ @Override
+ public int hashCode() {
+ return myChildRole.hashCode();
+ }
+
+ public static <E extends JpsElement> JpsElementCollectionRole<E> create(@NotNull JpsElementChildRole<E> role) {
+ return new JpsElementCollectionRole<E>(role);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementContainerEx.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementContainerEx.java
new file mode 100644
index 000000000000..79edd620632a
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementContainerEx.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementContainer;
+
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementContainerEx implements JpsElementContainer {
+ protected abstract Map<JpsElementChildRole<?>, JpsElement> getElementsMap();
+
+ protected abstract void applyChanges(JpsElementContainerEx modified);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementReferenceBase.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementReferenceBase.java
new file mode 100644
index 000000000000..5279796878c0
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsElementReferenceBase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementReferenceBase<E extends JpsElementReferenceBase<E, T>, T extends JpsElement> extends JpsElementBase<E>
+ implements JpsElementReference<T> {
+ @Override
+ public JpsElementReference<T> asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java
new file mode 100644
index 000000000000..7b7fe8011f03
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author nik
+ */
+public abstract class JpsExElementFactory {
+ public static JpsExElementFactory getInstance() {
+ return InstanceHolder.INSTANCE;
+ }
+
+ public abstract <E extends JpsElement> JpsElementCollection<E> createCollection(JpsElementChildRole<E> role);
+
+ public abstract JpsElementContainerEx createContainer(@NotNull JpsCompositeElementBase<?> parent);
+
+ public abstract JpsElementContainerEx createContainerCopy(@NotNull JpsElementContainerEx original,
+ @NotNull JpsCompositeElementBase<?> parent);
+
+ private static final class InstanceHolder {
+ private static final JpsExElementFactory INSTANCE = JpsServiceManager.getInstance().getService(JpsExElementFactory.class);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedCompositeElementBase.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedCompositeElementBase.java
new file mode 100644
index 000000000000..b941777f3595
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedCompositeElementBase.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+
+/**
+ * @author nik
+ */
+public abstract class JpsNamedCompositeElementBase<Self extends JpsNamedCompositeElementBase<Self>> extends JpsCompositeElementBase<Self>
+ implements JpsNamedElement {
+ private String myName;
+
+ protected JpsNamedCompositeElementBase(@NotNull String name) {
+ super();
+ myName = name;
+ }
+
+ protected JpsNamedCompositeElementBase(JpsNamedCompositeElementBase<Self> original) {
+ super(original);
+ myName = original.myName;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ public void applyChanges(@NotNull Self modified) {
+ super.applyChanges(modified);
+ setName(modified.getName());
+ }
+
+ @Override
+ public void setName(@NotNull String name) {
+ if (!myName.equals(name)) {
+ String oldName = myName;
+ myName = name;
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementRenamed(this, oldName, name);
+ }
+ }
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/ExplodedDirectoryModuleExtension.java b/jps/model-api/src/org/jetbrains/jps/model/java/ExplodedDirectoryModuleExtension.java
new file mode 100644
index 000000000000..89aae1e54775
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/ExplodedDirectoryModuleExtension.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+//todo[nik] move to j2me plugin
+public interface ExplodedDirectoryModuleExtension extends JpsElement {
+
+ String getExplodedUrl();
+
+ void setExplodedUrl(String explodedUrl);
+
+ boolean isExcludeExploded();
+
+ void setExcludeExploded(boolean excludeExploded);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootProperties.java b/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootProperties.java
new file mode 100644
index 000000000000..fcf046926251
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootProperties.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class JavaSourceRootProperties {
+ private final String myPackagePrefix;
+
+ public JavaSourceRootProperties() {
+ myPackagePrefix = "";
+ }
+
+ public JavaSourceRootProperties(@NotNull String packagePrefix) {
+ myPackagePrefix = packagePrefix;
+ }
+
+ @NotNull
+ public String getPackagePrefix() {
+ return myPackagePrefix;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootType.java
new file mode 100644
index 000000000000..2a181f1cd485
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JavaSourceRootType.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+/**
+ * @author nik
+ */
+public class JavaSourceRootType extends JpsModuleSourceRootType<JpsSimpleElement<JavaSourceRootProperties>> implements JpsElementTypeWithDefaultProperties<JpsSimpleElement<JavaSourceRootProperties>> {
+ public static final JavaSourceRootType SOURCE = new JavaSourceRootType();
+ public static final JavaSourceRootType TEST_SOURCE = new JavaSourceRootType();
+
+ private JavaSourceRootType() {
+ }
+
+ @NotNull
+ @Override
+ public JpsSimpleElement<JavaSourceRootProperties> createDefaultProperties() {
+ return JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties());
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java b/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java
new file mode 100644
index 000000000000..2f5aaa6d4c19
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author nik
+ */
+public abstract class JdkVersionDetector {
+ public static JdkVersionDetector getInstance() {
+ return JpsServiceManager.getInstance().getService(JdkVersionDetector.class);
+ }
+
+ @Nullable
+ public abstract String detectJdkVersion(String homePath);
+
+ @Nullable
+ public abstract String detectJdkVersion(String homePath, ActionRunner actionRunner);
+
+ @Nullable
+ public abstract String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
+ ActionRunner actionRunner);
+
+ //todo[nik] replace with a service with difference implementation for IDEA and for JPS process (need to exclude jps-builders module from IDEA classpath)
+ public interface ActionRunner {
+ Future<?> run(Runnable runnable);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java
new file mode 100644
index 000000000000..5253d7ccf28d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+
+/**
+ * @author nik
+ */
+public class JpsAnnotationRootType extends JpsOrderRootType {
+ public static final JpsAnnotationRootType INSTANCE = new JpsAnnotationRootType();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaClasspathKind.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaClasspathKind.java
new file mode 100644
index 000000000000..5daa2dfc5271
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaClasspathKind.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+/**
+ * @author nik
+ */
+public enum JpsJavaClasspathKind {
+ PRODUCTION_COMPILE, PRODUCTION_RUNTIME,
+ TEST_COMPILE, TEST_RUNTIME;
+
+ public boolean isTestsIncluded() {
+ return this == TEST_COMPILE || this == TEST_RUNTIME;
+ }
+
+ public boolean isRuntime() {
+ return this == PRODUCTION_RUNTIME || this == TEST_RUNTIME;
+ }
+
+ public static JpsJavaClasspathKind compile(boolean tests) {
+ return tests ? TEST_COMPILE : PRODUCTION_COMPILE;
+ }
+
+ public static JpsJavaClasspathKind runtime(boolean tests) {
+ return tests ? TEST_RUNTIME : PRODUCTION_RUNTIME;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java
new file mode 100644
index 000000000000..78d6d622fc06
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import com.intellij.openapi.util.Condition;
+import org.jetbrains.jps.model.module.JpsDependenciesEnumerator;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaDependenciesEnumerator extends JpsDependenciesEnumerator {
+ JpsJavaDependenciesEnumerator productionOnly();
+ JpsJavaDependenciesEnumerator compileOnly();
+ JpsJavaDependenciesEnumerator runtimeOnly();
+ JpsJavaDependenciesEnumerator exportedOnly();
+
+ JpsJavaDependenciesEnumerator withoutLibraries();
+ JpsJavaDependenciesEnumerator withoutDepModules();
+ JpsJavaDependenciesEnumerator withoutSdk();
+ JpsJavaDependenciesEnumerator withoutModuleSourceEntries();
+
+ @Override
+ JpsJavaDependenciesEnumerator recursively();
+
+ @Override
+ JpsJavaDependenciesEnumerator satisfying(Condition<JpsDependencyElement> condition);
+
+ JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind);
+
+ JpsJavaDependenciesRootsEnumerator classes();
+ JpsJavaDependenciesRootsEnumerator sources();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesRootsEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesRootsEnumerator.java
new file mode 100644
index 000000000000..b294ac5483c1
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesRootsEnumerator.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.module.JpsDependenciesRootsEnumerator;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaDependenciesRootsEnumerator extends JpsDependenciesRootsEnumerator {
+ JpsJavaDependenciesRootsEnumerator withoutSelfModuleOutput();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyExtension.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyExtension.java
new file mode 100644
index 000000000000..47f49d4ac49f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyExtension.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaDependencyExtension extends JpsElement {
+ boolean isExported();
+
+ void setExported(boolean exported);
+
+ @NotNull
+ JpsJavaDependencyScope getScope();
+
+ void setScope(@NotNull JpsJavaDependencyScope scope);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyScope.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyScope.java
new file mode 100644
index 000000000000..5a42e0957fa2
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependencyScope.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+
+import static org.jetbrains.jps.model.java.JpsJavaClasspathKind.*;
+
+/**
+ * @author nik
+ */
+public enum JpsJavaDependencyScope {
+ COMPILE(PRODUCTION_COMPILE, PRODUCTION_RUNTIME, TEST_COMPILE, TEST_RUNTIME),
+ TEST(TEST_COMPILE, TEST_RUNTIME),
+ RUNTIME(PRODUCTION_RUNTIME, TEST_RUNTIME),
+ PROVIDED(PRODUCTION_COMPILE, TEST_COMPILE, TEST_RUNTIME);
+ private EnumSet<JpsJavaClasspathKind> myAffectedClasspath;
+
+ JpsJavaDependencyScope(JpsJavaClasspathKind... classpath) {
+ myAffectedClasspath = EnumSet.copyOf(Arrays.asList(classpath));
+ }
+
+ public boolean isIncludedIn(JpsJavaClasspathKind kind) {
+ return myAffectedClasspath.contains(kind);
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java
new file mode 100644
index 000000000000..12df795d34a0
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsGlobal;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationProperties;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationState;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsJavaExtensionService {
+ public static JpsJavaExtensionService getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsJavaExtensionService.class);
+ }
+
+ public static JpsJavaDependenciesEnumerator dependencies(JpsModule module) {
+ return getInstance().enumerateDependencies(module);
+ }
+
+ public static JpsJavaDependenciesEnumerator dependencies(JpsProject project) {
+ return getInstance().enumerateDependencies(project);
+ }
+
+ @NotNull
+ public abstract JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference);
+
+ @NotNull
+ public abstract JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference);
+
+ public abstract JpsJavaDependenciesEnumerator enumerateDependencies(Collection<JpsModule> modules);
+
+ protected abstract JpsJavaDependenciesEnumerator enumerateDependencies(JpsProject project);
+
+ protected abstract JpsJavaDependenciesEnumerator enumerateDependencies(JpsModule module);
+
+ @NotNull
+ public abstract JpsJavaProjectExtension getOrCreateProjectExtension(@NotNull JpsProject project);
+
+ @Nullable
+ public abstract JpsJavaProjectExtension getProjectExtension(@NotNull JpsProject project);
+
+
+ @NotNull
+ public abstract JpsJavaModuleExtension getOrCreateModuleExtension(@NotNull JpsModule module);
+
+ @Nullable
+ public abstract JpsJavaModuleExtension getModuleExtension(@NotNull JpsModule module);
+
+ @NotNull
+ public abstract JpsJavaDependencyExtension getOrCreateDependencyExtension(@NotNull JpsDependencyElement dependency);
+
+ @Nullable
+ public abstract JpsJavaDependencyExtension getDependencyExtension(@NotNull JpsDependencyElement dependency);
+
+ @Nullable
+ public abstract ExplodedDirectoryModuleExtension getExplodedDirectoryExtension(@NotNull JpsModule module);
+
+ @NotNull
+ public abstract ExplodedDirectoryModuleExtension getOrCreateExplodedDirectoryExtension(@NotNull JpsModule module);
+
+ @NotNull
+ public abstract List<JpsDependencyElement> getDependencies(JpsModule module, JpsJavaClasspathKind classpathKind, boolean exportedOnly);
+
+ @Nullable
+ public abstract LanguageLevel getLanguageLevel(JpsModule module);
+
+ @Nullable
+ public abstract String getOutputUrl(JpsModule module, boolean forTests);
+
+ @Nullable
+ public abstract File getOutputDirectory(JpsModule module, boolean forTests);
+
+ public abstract JpsTypedLibrary<JpsSdk<JpsDummyElement>> addJavaSdk(@NotNull JpsGlobal global, @NotNull String name,
+ @NotNull String homePath);
+
+ @Nullable
+ public abstract JpsJavaCompilerConfiguration getCompilerConfiguration(@NotNull JpsProject project);
+
+ @NotNull
+ public abstract JpsJavaCompilerConfiguration getOrCreateCompilerConfiguration(@NotNull JpsProject project);
+
+ @NotNull
+ public abstract JpsSdkReference<JpsDummyElement> createWrappedJavaSdkReference(@NotNull JpsJavaSdkTypeWrapper sdkType,
+ @NotNull JpsSdkReference<?> wrapperReference);
+
+ @NotNull
+ public abstract JpsApplicationRunConfigurationProperties createRunConfigurationProperties(JpsApplicationRunConfigurationState state);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaLibraryType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaLibraryType.java
new file mode 100644
index 000000000000..533036071ee8
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaLibraryType.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+
+/**
+ * @author nik
+ */
+public class JpsJavaLibraryType extends JpsLibraryType<JpsDummyElement> implements JpsElementTypeWithDefaultProperties<JpsDummyElement> {
+ public static final JpsJavaLibraryType INSTANCE = new JpsJavaLibraryType();
+
+ @NotNull
+ @Override
+ public JpsDummyElement createDefaultProperties() {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleExtension.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleExtension.java
new file mode 100644
index 000000000000..725063f68ddb
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleExtension.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsUrlList;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaModuleExtension extends JpsElement {
+ JpsUrlList getJavadocRoots();
+
+ JpsUrlList getAnnotationRoots();
+
+ String getOutputUrl();
+
+ void setOutputUrl(String outputUrl);
+
+ String getTestOutputUrl();
+
+ void setTestOutputUrl(String testOutputUrl);
+
+ LanguageLevel getLanguageLevel();
+
+ void setLanguageLevel(LanguageLevel languageLevel);
+
+ boolean isInheritOutput();
+
+ void setInheritOutput(boolean inheritOutput);
+
+ boolean isExcludeOutput();
+
+ void setExcludeOutput(boolean excludeOutput);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleType.java
new file mode 100644
index 000000000000..6a971cf7b8ef
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaModuleType.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+import org.jetbrains.jps.model.module.JpsModuleType;
+
+/**
+ * @author nik
+ */
+public class JpsJavaModuleType extends JpsModuleType<JpsDummyElement> implements JpsElementTypeWithDefaultProperties<JpsDummyElement> {
+ public static final JpsJavaModuleType INSTANCE = new JpsJavaModuleType();
+
+ @NotNull
+ @Override
+ public JpsDummyElement createDefaultProperties() {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaProjectExtension.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaProjectExtension.java
new file mode 100644
index 000000000000..f13193cc9d0c
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaProjectExtension.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaProjectExtension extends JpsElement {
+ String getOutputUrl();
+
+ void setOutputUrl(String outputUrl);
+
+ LanguageLevel getLanguageLevel();
+
+ void setLanguageLevel(LanguageLevel languageLevel);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkType.java
new file mode 100644
index 000000000000..3ebba24ab1d5
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkType.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+
+/**
+ * @author nik
+ */
+public class JpsJavaSdkType extends JpsSdkType<JpsDummyElement> implements JpsElementTypeWithDefaultProperties<JpsDummyElement> {
+ public static final JpsJavaSdkType INSTANCE = new JpsJavaSdkType();
+
+ @NotNull
+ @Override
+ public JpsDummyElement createDefaultProperties() {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+
+ public static String getJavaExecutable(JpsSdk<?> sdk) {
+ return sdk.getHomePath() + "/bin/java";
+ }
+
+ @Override
+ public String toString() {
+ return "java sdk type";
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkTypeWrapper.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkTypeWrapper.java
new file mode 100644
index 000000000000..39c44502d2e9
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaSdkTypeWrapper.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaSdkTypeWrapper {
+ @Nullable
+ String getJavaSdkName(@NotNull JpsElement properties);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java
new file mode 100644
index 000000000000..dd38cc74e845
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement;
+
+/**
+ * @author nik
+ */
+public interface JpsProductionModuleOutputPackagingElement extends JpsModuleOutputPackagingElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java
new file mode 100644
index 000000000000..ac7ea04c94c1
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement;
+
+/**
+ * @author nik
+ */
+public interface JpsTestModuleOutputPackagingElement extends JpsModuleOutputPackagingElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/LanguageLevel.java b/jps/model-api/src/org/jetbrains/jps/model/java/LanguageLevel.java
new file mode 100644
index 000000000000..689776eafda0
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/LanguageLevel.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java;
+
+/**
+ * @author nik
+ */
+public enum LanguageLevel {
+ JDK_1_3, JDK_1_4, JDK_1_5, JDK_1_6, JDK_1_7, JDK_1_8
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java
new file mode 100644
index 000000000000..91009b952740
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 5/27/12
+ */
+public interface AnnotationProcessingConfiguration {
+ boolean isEnabled();
+
+ @NotNull
+ String getProcessorPath();
+
+ @NotNull
+ String getGeneratedSourcesDirectoryName(boolean forTests);
+
+ boolean isOutputRelativeToContentRoot();
+
+ @NotNull
+ Set<String> getProcessors();
+
+ @NotNull
+ Map<String, String> getProcessorOptions();
+
+ boolean isObtainProcessorsFromClasspath();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/EclipseCompilerOptions.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/EclipseCompilerOptions.java
new file mode 100644
index 000000000000..5593324ba6bd
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/EclipseCompilerOptions.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/28/12
+ */
+public class EclipseCompilerOptions extends JpsJavaCompilerOptions{
+ public boolean PROCEED_ON_ERROR = true;
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JavaCompilers.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JavaCompilers.java
new file mode 100644
index 000000000000..ba9a8bd64202
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JavaCompilers.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+public interface JavaCompilers {
+ String JAVAC_ID = "Javac";
+ String JAVAC_API_ID = "compAPI";
+ String ECLIPSE_ID = "Eclipse";
+ String ECLIPSE_EMBEDDED_ID = "EclipseEmbedded";
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JikesCompilerOptions.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JikesCompilerOptions.java
new file mode 100644
index 000000000000..81446eba546b
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JikesCompilerOptions.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/28/12
+ */
+public class JikesCompilerOptions extends JpsJavaCompilerOptions{
+ public String JIKES_PATH = "";
+ public boolean IS_EMACS_ERRORS_MODE = true;
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsCompilerExcludes.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsCompilerExcludes.java
new file mode 100644
index 000000000000..bea08537e9b1
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsCompilerExcludes.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface JpsCompilerExcludes {
+ void addExcludedFile(String url);
+
+ void addExcludedDirectory(String url, boolean recursively);
+
+ boolean isExcluded(File file);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java
new file mode 100644
index 000000000000..8aaf77b1687d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsJavaCompilerConfiguration extends JpsElement {
+ boolean isAddNotNullAssertions();
+ void setAddNotNullAssertions(boolean addNotNullAssertions);
+
+ boolean isClearOutputDirectoryOnRebuild();
+ void setClearOutputDirectoryOnRebuild(boolean clearOutputDirectoryOnRebuild);
+
+ @NotNull
+ JpsCompilerExcludes getCompilerExcludes();
+
+ @NotNull
+ ProcessorConfigProfile getDefaultAnnotationProcessingProfile();
+ ProcessorConfigProfile addAnnotationProcessingProfile();
+
+ /**
+ * @return a list of currently configured profiles excluding default one
+ */
+ @NotNull
+ Collection<ProcessorConfigProfile> getAnnotationProcessingProfiles();
+
+ /**
+ * @param module
+ * @return annotation profile with which the given module is associated
+ */
+ @NotNull
+ ProcessorConfigProfile getAnnotationProcessingProfile(JpsModule module);
+
+ void addResourcePattern(String pattern);
+ List<String> getResourcePatterns();
+
+
+ @Nullable
+ String getByteCodeTargetLevel(String moduleName);
+
+ void setProjectByteCodeTargetLevel(String level);
+ void setModuleByteCodeTargetLevel(String moduleName, String level);
+
+ @NotNull
+ String getJavaCompilerId();
+ void setJavaCompilerId(@NotNull String compiler);
+
+ @NotNull
+ JpsJavaCompilerOptions getCompilerOptions(@NotNull String compilerId);
+ void setCompilerOptions(@NotNull String compilerId, @NotNull JpsJavaCompilerOptions options);
+
+ @NotNull
+ JpsJavaCompilerOptions getCurrentCompilerOptions();
+
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerOptions.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerOptions.java
new file mode 100644
index 000000000000..46862d4ac5dc
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerOptions.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author nik
+ */
+public class JpsJavaCompilerOptions {
+ public boolean DEBUGGING_INFO = true;
+ public boolean GENERATE_NO_WARNINGS = false;
+ public boolean DEPRECATION = true;
+ public String ADDITIONAL_OPTIONS_STRING = "";
+ public int MAXIMUM_HEAP_SIZE = 128;
+
+ private boolean myTestsUseExternalCompiler = false;
+
+ @TestOnly
+ public boolean isTestsUseExternalCompiler() {
+ return myTestsUseExternalCompiler;
+ }
+
+ @TestOnly
+ public void setTestsUseExternalCompiler(boolean testsUseExternalCompiler) {
+ myTestsUseExternalCompiler = testsUseExternalCompiler;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java
new file mode 100644
index 000000000000..b65fd945ca6e
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public interface ProcessorConfigProfile extends AnnotationProcessingConfiguration {
+ String DEFAULT_PRODUCTION_DIR_NAME = "generated";
+ String DEFAULT_TESTS_DIR_NAME = "generated_tests";
+
+ void initFrom(ProcessorConfigProfile other);
+
+ String getName();
+
+ void setName(String name);
+
+ void setEnabled(boolean enabled);
+
+ void setProcessorPath(@Nullable String processorPath);
+
+ void setObtainProcessorsFromClasspath(boolean value);
+
+ void setGeneratedSourcesDirectoryName(@Nullable String generatedSourcesDirectoryName, boolean forTests);
+
+ @NotNull
+ Set<String> getModuleNames();
+
+ boolean addModuleName(String name);
+
+ boolean addModuleNames(Collection<String> names);
+
+ boolean removeModuleName(String name);
+
+ boolean removeModuleNames(Collection<String> names);
+
+ void clearModuleNames();
+
+ void clearProcessors();
+
+ boolean addProcessor(String processor);
+
+ boolean removeProcessor(String processor);
+
+ String setOption(String key, String value);
+
+ @Nullable
+ String getOption(String key);
+
+ void clearProcessorOptions();
+
+ void setOutputRelativeToContentRoot(boolean outputRelativeToContentRoot);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/RmicCompilerOptions.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/RmicCompilerOptions.java
new file mode 100644
index 000000000000..c91fd62e7a21
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/RmicCompilerOptions.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.compiler;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/28/12
+ */
+public class RmicCompilerOptions extends JpsJavaCompilerOptions{
+ public boolean IS_EANABLED = false;
+ public boolean GENERATE_IIOP_STUBS = false;
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationProperties.java b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationProperties.java
new file mode 100644
index 000000000000..7804a5f1ff90
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationProperties.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.runConfiguration;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsApplicationRunConfigurationProperties extends JpsElement {
+ String getMainClass();
+ void setMainClass(String value);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationState.java b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationState.java
new file mode 100644
index 000000000000..6dc0c25b4cb7
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationState.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.runConfiguration;
+
+/**
+* @author nik
+*/
+public class JpsApplicationRunConfigurationState {
+ public String MAIN_CLASS_NAME;
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationType.java b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationType.java
new file mode 100644
index 000000000000..aa0a7a268d91
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/runConfiguration/JpsApplicationRunConfigurationType.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.runConfiguration;
+
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfigurationType;
+
+/**
+ * @author nik
+ */
+public class JpsApplicationRunConfigurationType extends JpsRunConfigurationType<JpsApplicationRunConfigurationProperties> {
+ public static final JpsApplicationRunConfigurationType INSTANCE = new JpsApplicationRunConfigurationType();
+
+ private JpsApplicationRunConfigurationType() {
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java
new file mode 100644
index 000000000000..242c7300e0c7
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsNamedElement;
+import org.jetbrains.jps.model.JpsReferenceableElement;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsLibrary extends JpsNamedElement, JpsReferenceableElement<JpsLibrary> {
+
+ @NotNull
+ List<JpsLibraryRoot> getRoots(@NotNull JpsOrderRootType rootType);
+
+ void addRoot(@NotNull String url, @NotNull JpsOrderRootType rootType);
+
+ void addRoot(@NotNull File file, @NotNull JpsOrderRootType rootType);
+
+ void addRoot(@NotNull String url, @NotNull JpsOrderRootType rootType, @NotNull JpsLibraryRoot.InclusionOptions options);
+
+ void removeUrl(@NotNull String url, @NotNull JpsOrderRootType rootType);
+
+ void delete();
+
+ @NotNull
+ JpsLibraryReference createReference();
+
+ @NotNull
+ JpsLibraryType<?> getType();
+
+ @Nullable
+ <P extends JpsElement>
+ JpsTypedLibrary<P> asTyped(@NotNull JpsLibraryType<P> type);
+
+ @NotNull
+ JpsElement getProperties();
+
+ List<File> getFiles(final JpsOrderRootType rootType);
+
+ List<String> getRootUrls(final JpsOrderRootType rootType);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryCollection.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryCollection.java
new file mode 100644
index 000000000000..f28650ac000c
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryCollection.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryCollection {
+ @NotNull
+ <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull String name, @NotNull LibraryType type);
+
+ @NotNull
+ <P extends JpsElement>
+ JpsTypedLibrary<P> addLibrary(@NotNull String name, @NotNull JpsLibraryType<P> type, @NotNull P properties);
+
+ @NotNull
+ List<JpsLibrary> getLibraries();
+
+ @NotNull
+ <P extends JpsElement>
+ Iterable<JpsTypedLibrary<P>> getLibraries(@NotNull JpsLibraryType<P> type);
+
+ void addLibrary(@NotNull JpsLibrary library);
+
+ @Nullable
+ JpsLibrary findLibrary(@NotNull String name);
+
+ @Nullable
+ <E extends JpsElement> JpsTypedLibrary<E> findLibrary(@NotNull String name, @NotNull JpsLibraryType<E> type);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryListener.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryListener.java
new file mode 100644
index 000000000000..a7c93795dd66
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryListener extends EventListener {
+ void libraryAdded(@NotNull JpsLibrary library);
+ void libraryRemoved(@NotNull JpsLibrary library);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryReference.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryReference.java
new file mode 100644
index 000000000000..06e7f6066859
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryReference.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryReference extends JpsElementReference<JpsLibrary> {
+ @NotNull
+ String getLibraryName();
+
+ @Override
+ JpsLibraryReference asExternal(@NotNull JpsModel model);
+
+ JpsElementReference<? extends JpsCompositeElement> getParentReference();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRoot.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRoot.java
new file mode 100644
index 000000000000..6089ff4152ce
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRoot.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryRoot extends JpsElement {
+ @NotNull
+ JpsOrderRootType getRootType();
+
+ @NotNull
+ String getUrl();
+
+ @NotNull
+ InclusionOptions getInclusionOptions();
+
+ @NotNull
+ JpsLibrary getLibrary();
+
+ enum InclusionOptions {ROOT_ITSELF, ARCHIVES_UNDER_ROOT, ARCHIVES_UNDER_ROOT_RECURSIVELY}
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRootListener.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRootListener.java
new file mode 100644
index 000000000000..27808df952ed
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryRootListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryRootListener extends EventListener {
+ void rootAdded(@NotNull JpsLibraryRoot root);
+ void rootRemoved(@NotNull JpsLibraryRoot root);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryType.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryType.java
new file mode 100644
index 000000000000..81a1de0fa604
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibraryType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+
+/**
+ * @author nik
+ */
+public abstract class JpsLibraryType<P extends JpsElement> extends JpsElementType<P> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java
new file mode 100644
index 000000000000..89fa4efc4187
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+/**
+ * @author nik
+ */
+public abstract class JpsOrderRootType {
+ public static final JpsOrderRootType COMPILED = new JpsOrderRootType() {
+ };
+ public static final JpsOrderRootType SOURCES = new JpsOrderRootType() {
+ };
+ public static final JpsOrderRootType DOCUMENTATION = new JpsOrderRootType() {
+ };
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsTypedLibrary.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsTypedLibrary.java
new file mode 100644
index 000000000000..3466139a71ab
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsTypedLibrary.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsTypedElement;
+
+/**
+ * @author nik
+ */
+public interface JpsTypedLibrary<P extends JpsElement> extends JpsLibrary, JpsTypedElement<P> {
+ @NotNull
+ @Override
+ JpsLibraryType<P> getType();
+
+ @NotNull
+ @Override
+ P getProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdk.java b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdk.java
new file mode 100644
index 000000000000..26da034da738
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdk.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.sdk;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.library.JpsLibrary;
+
+/**
+ * @author nik
+ */
+public interface JpsSdk<P extends JpsElement> extends JpsElement {
+
+ @NotNull
+ JpsLibrary getParent();
+
+ String getHomePath();
+
+ void setHomePath(String homePath);
+
+ String getVersionString();
+
+ void setVersionString(String versionString);
+
+ JpsSdkType<P> getSdkType();
+
+ P getSdkProperties();
+
+ JpsSdkReference<P> createReference();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java
new file mode 100644
index 000000000000..390fbdd6ca8d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.sdk;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+
+/**
+ * @author nik
+ */
+public interface JpsSdkReference<P extends JpsElement> extends JpsElementReference<JpsTypedLibrary<JpsSdk<P>>> {
+ String getSdkName();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkType.java b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkType.java
new file mode 100644
index 000000000000..2699fdf8ec57
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkType.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.sdk;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+
+/**
+ * @author nik
+ */
+public abstract class JpsSdkType<P extends JpsElement> extends JpsLibraryType<JpsSdk<P>> {
+ private final JpsElementChildRole<P> mySdkPropertiesRole = new JpsElementChildRole<P>();
+
+ public final JpsElementChildRole<P> getSdkPropertiesRole() {
+ return mySdkPropertiesRole;
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java
new file mode 100644
index 000000000000..c31ab23ad8d6
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.Consumer;
+import org.jetbrains.jps.model.library.JpsLibrary;
+
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public interface JpsDependenciesEnumerator {
+ JpsDependenciesEnumerator withoutLibraries();
+ JpsDependenciesEnumerator withoutDepModules();
+ JpsDependenciesEnumerator withoutSdk();
+ JpsDependenciesEnumerator withoutModuleSourceEntries();
+ JpsDependenciesEnumerator recursively();
+ JpsDependenciesEnumerator satisfying(Condition<JpsDependencyElement> condition);
+
+ Set<JpsModule> getModules();
+ Set<JpsLibrary> getLibraries();
+
+ void processModules(Consumer<JpsModule> consumer);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesList.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesList.java
new file mode 100644
index 000000000000..aca1be3d3779
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesList.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsDependenciesList extends JpsElement {
+ @NotNull
+ JpsModuleDependency addModuleDependency(@NotNull JpsModule module);
+
+ @NotNull
+ JpsModuleDependency addModuleDependency(@NotNull JpsModuleReference moduleReference);
+
+ @NotNull
+ JpsLibraryDependency addLibraryDependency(@NotNull JpsLibrary libraryElement);
+
+ @NotNull
+ JpsLibraryDependency addLibraryDependency(@NotNull JpsLibraryReference libraryReference);
+
+ void addModuleSourceDependency();
+
+ void addSdkDependency(@NotNull JpsSdkType<?> sdkType);
+
+ @NotNull
+ List<JpsDependencyElement> getDependencies();
+
+ void clear();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesRootsEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesRootsEnumerator.java
new file mode 100644
index 000000000000..44962f6c26ec
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesRootsEnumerator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public interface JpsDependenciesRootsEnumerator {
+ Collection<String> getUrls();
+
+ Collection<File> getRoots();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java
new file mode 100644
index 000000000000..45d21d247fe6
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsCompositeElement;
+
+/**
+ * @author nik
+ */
+public interface JpsDependencyElement extends JpsCompositeElement {
+ void remove();
+
+ JpsModule getContainingModule();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacet.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacet.java
new file mode 100644
index 000000000000..e4fac75ac921
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacet.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsNamedElement;
+import org.jetbrains.jps.model.JpsReferenceableElement;
+
+/**
+ * @author nik
+ */
+//todo[nik] I'm not sure that we really need separate interface for facets in the project model.
+//Perhaps facets should be replaced by extensions for module elements
+public interface JpsFacet extends JpsNamedElement, JpsReferenceableElement<JpsFacet> {
+
+ JpsModule getModule();
+
+ @NotNull
+ JpsFacetType<?> getType();
+
+ void delete();
+
+ @NotNull
+ @Override
+ JpsFacetReference createReference();
+
+ void setParentFacet(@NotNull JpsFacet facet);
+
+ @Nullable
+ JpsFacet getParentFacet();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetListener.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetListener.java
new file mode 100644
index 000000000000..582e35bfc8aa
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsFacetListener extends EventListener {
+ void facetAdded(JpsFacet facet);
+ void facetRemoved(JpsFacet facet);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetReference.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetReference.java
new file mode 100644
index 000000000000..f4754b45242c
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetReference.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsElementReference;
+
+/**
+ * @author nik
+ */
+public interface JpsFacetReference extends JpsElementReference<JpsFacet> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetType.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetType.java
new file mode 100644
index 000000000000..4ae5adc90d5d
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsFacetType.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+//todo[nik] I'm not sure that we really need separate interface for facets in the project model.
+//Perhaps facets should be replaced by extensions for module elements
+public abstract class JpsFacetType<P extends JpsElement> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsLibraryDependency.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsLibraryDependency.java
new file mode 100644
index 000000000000..919f8d303686
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsLibraryDependency.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+
+/**
+ * @author nik
+ */
+public interface JpsLibraryDependency extends JpsDependencyElement {
+ @NotNull
+ JpsLibraryReference getLibraryReference();
+
+ @Nullable
+ JpsLibrary getLibrary();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java
new file mode 100644
index 000000000000..668b4f18c372
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryCollection;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public interface JpsModule extends JpsNamedElement, JpsReferenceableElement<JpsModule>, JpsCompositeElement {
+ @NotNull
+ JpsUrlList getContentRootsList();
+
+ @NotNull
+ JpsUrlList getExcludeRootsList();
+
+ @NotNull
+ List<JpsModuleSourceRoot> getSourceRoots();
+
+ @NotNull
+ <P extends JpsElement>
+ Iterable<JpsTypedModuleSourceRoot<P>> getSourceRoots(@NotNull JpsModuleSourceRootType<P> type);
+
+ @NotNull
+ <P extends JpsElement, Type extends JpsModuleSourceRootType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsModuleSourceRoot addSourceRoot(@NotNull String url, @NotNull Type rootType);
+
+ @NotNull
+ <P extends JpsElement>
+ JpsModuleSourceRoot addSourceRoot(@NotNull String url, @NotNull JpsModuleSourceRootType<P> rootType, @NotNull P properties);
+
+ void removeSourceRoot(@NotNull String url, @NotNull JpsModuleSourceRootType rootType);
+
+ @NotNull
+ <P extends JpsElement>
+ JpsFacet addFacet(@NotNull String name, @NotNull JpsFacetType<P> type, @NotNull P properties);
+
+ @NotNull
+ List<JpsFacet> getFacets();
+
+ JpsDependenciesList getDependenciesList();
+
+ @NotNull
+ JpsModuleReference createReference();
+
+ @NotNull
+ <P extends JpsElement, Type extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addModuleLibrary(@NotNull String name, @NotNull Type type);
+
+ void addModuleLibrary(@NotNull JpsLibrary library);
+
+ @NotNull
+ JpsLibraryCollection getLibraryCollection();
+
+ @NotNull
+ JpsSdkReferencesTable getSdkReferencesTable();
+
+ @Nullable
+ <P extends JpsElement>
+ JpsSdkReference<P> getSdkReference(@NotNull JpsSdkType<P> type);
+
+ @Nullable
+ <P extends JpsElement>
+ JpsSdk<P> getSdk(@NotNull JpsSdkType<P> type);
+
+ void delete();
+
+ JpsProject getProject();
+
+ @NotNull
+ JpsModuleType<?> getModuleType();
+
+ @NotNull
+ JpsElement getProperties();
+
+ @Nullable
+ <P extends JpsElement> JpsTypedModule<P> asTyped(@NotNull JpsModuleType<P> type);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleContentRootsListener.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleContentRootsListener.java
new file mode 100644
index 000000000000..8dde5906fa68
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleContentRootsListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsUrlListChangeListener;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleContentRootsListener extends JpsUrlListChangeListener<JpsModule> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleDependency.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleDependency.java
new file mode 100644
index 000000000000..c8ea987f59c0
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleDependency.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleDependency extends JpsDependencyElement {
+ @NotNull
+ JpsModuleReference getModuleReference();
+
+ @Nullable
+ JpsModule getModule();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleExcludeRootsListener.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleExcludeRootsListener.java
new file mode 100644
index 000000000000..da2373fce141
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleExcludeRootsListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsUrlListChangeListener;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleExcludeRootsListener extends JpsUrlListChangeListener<JpsModule> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleListener.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleListener.java
new file mode 100644
index 000000000000..c24b32bf7cdc
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleListener extends EventListener {
+ void moduleAdded(@NotNull JpsModule module);
+ void moduleRemoved(@NotNull JpsModule module);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleReference.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleReference.java
new file mode 100644
index 000000000000..695fb33bc14c
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleReference.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleReference extends JpsElementReference<JpsModule> {
+ @NotNull
+ String getModuleName();
+
+ @Override
+ JpsModuleReference asExternal(@NotNull JpsModel model);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceDependency.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceDependency.java
new file mode 100644
index 000000000000..6fd3d94355d2
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceDependency.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleSourceDependency extends JpsDependencyElement {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java
new file mode 100644
index 000000000000..713b18d2e70e
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleSourceRoot extends JpsElement {
+ @NotNull
+ JpsModuleSourceRootType<?> getRootType();
+
+ @Nullable
+ <P extends JpsElement> P getProperties(@NotNull JpsModuleSourceRootType<P> type);
+
+ @Nullable
+ <P extends JpsElement> JpsTypedModuleSourceRoot<P> asTyped(@NotNull JpsModuleSourceRootType<P> type);
+
+ @NotNull
+ JpsElement getProperties();
+
+ @NotNull
+ String getUrl();
+
+ @NotNull
+ File getFile();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootListener.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootListener.java
new file mode 100644
index 000000000000..1c1ee25ce1cc
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleSourceRootListener extends EventListener {
+ void sourceRootAdded(@NotNull JpsModuleSourceRoot root);
+ void sourceRootRemoved(@NotNull JpsModuleSourceRoot root);
+ void sourceRootChanged(@NotNull JpsModuleSourceRoot root);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootType.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootType.java
new file mode 100644
index 000000000000..5a2dbb34d9ad
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRootType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModuleSourceRootType<P extends JpsElement> extends JpsElementType<P> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleType.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleType.java
new file mode 100644
index 000000000000..9062744badea
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModuleType<P extends JpsElement> extends JpsElementType<P> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkDependency.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkDependency.java
new file mode 100644
index 000000000000..527414c65164
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkDependency.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+/**
+ * @author nik
+ */
+public interface JpsSdkDependency extends JpsDependencyElement {
+ @NotNull
+ JpsSdkType<?> getSdkType();
+
+ @Nullable
+ JpsLibrary resolveSdk();
+
+ @Nullable
+ JpsSdkReference<?> getSdkReference();
+
+ boolean isInherited();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkReferencesTable.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkReferencesTable.java
new file mode 100644
index 000000000000..033b520d8e80
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsSdkReferencesTable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+
+/**
+ * @author nik
+ */
+public interface JpsSdkReferencesTable extends JpsCompositeElement {
+ @Nullable
+ <P extends JpsElement>
+ JpsSdkReference<P> getSdkReference(@NotNull JpsSdkType<P> type);
+
+ <P extends JpsElement>
+ void setSdkReference(@NotNull JpsSdkType<P> type, @Nullable JpsSdkReference<P> sdkReference);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModule.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModule.java
new file mode 100644
index 000000000000..9c51dd5e3c9f
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModule.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsTypedElement;
+
+/**
+ * @author nik
+ */
+public interface JpsTypedModule<P extends JpsElement> extends JpsModule, JpsTypedElement<P> {
+ @NotNull
+ JpsModuleType<P> getModuleType();
+
+ @NotNull
+ @Override
+ P getProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModuleSourceRoot.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModuleSourceRoot.java
new file mode 100644
index 000000000000..9dc2cf00e455
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsTypedModuleSourceRoot.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsTypedElement;
+
+/**
+ * @author nik
+ */
+public interface JpsTypedModuleSourceRoot<P extends JpsElement> extends JpsModuleSourceRoot, JpsTypedElement<P> {
+ @NotNull
+ @Override
+ P getProperties();
+
+ @NotNull
+ @Override
+ JpsModuleSourceRootType<P> getRootType();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfiguration.java
new file mode 100644
index 000000000000..e515dbb4a1d5
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.runConfiguration;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsNamedElement;
+
+/**
+ * @author nik
+ */
+public interface JpsRunConfiguration extends JpsNamedElement, JpsCompositeElement {
+ @NotNull
+ JpsElement getProperties();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfigurationType.java b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfigurationType.java
new file mode 100644
index 000000000000..558bf0548396
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsRunConfigurationType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.runConfiguration;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+
+/**
+ * @author nik
+ */
+public abstract class JpsRunConfigurationType<P extends JpsElement> extends JpsElementType<P> {
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsTypedRunConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsTypedRunConfiguration.java
new file mode 100644
index 000000000000..16fa853721b1
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/runConfiguration/JpsTypedRunConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.runConfiguration;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsTypedElement;
+
+/**
+ * @author nik
+ */
+public interface JpsTypedRunConfiguration<P extends JpsElement> extends JpsRunConfiguration, JpsTypedElement<P> {
+ @NotNull
+ @Override
+ P getProperties();
+
+ @Override
+ JpsRunConfigurationType<P> getType();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java b/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java
new file mode 100644
index 000000000000..3bcb89aa3c79
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.service;
+
+import java.util.ServiceLoader;
+
+/**
+ * @author nik
+ */
+public abstract class JpsServiceManager {
+ public static JpsServiceManager getInstance() {
+ return InstanceHolder.INSTANCE;
+ }
+
+ public abstract <T> T getService(Class<T> serviceClass);
+
+ public abstract <T> Iterable<T> getExtensions(Class<T> extensionClass);
+
+ private static class InstanceHolder {
+ private static final JpsServiceManager INSTANCE;
+
+ static {
+ INSTANCE = ServiceLoader.load(JpsServiceManager.class, JpsServiceManager.class.getClassLoader()).iterator().next();
+ }
+ }
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/service/SharedThreadPool.java b/jps/model-api/src/org/jetbrains/jps/service/SharedThreadPool.java
new file mode 100644
index 000000000000..bb26dd49b031
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/service/SharedThreadPool.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.service;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+
+/**
+ * @author nik
+ */
+public abstract class SharedThreadPool implements Executor {
+ public static SharedThreadPool getInstance() {
+ return JpsServiceManager.getInstance().getService(SharedThreadPool.class);
+ }
+
+ public abstract Future<?> executeOnPooledThread(Runnable action);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java
new file mode 100644
index 000000000000..871ad091c264
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.util;
+
+import com.intellij.openapi.util.SystemInfoRt;
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JpsPathUtil {
+
+ public static boolean isUnder(Set<File> ancestors, File file) {
+ if (ancestors.isEmpty()) {
+ return false; // optimization
+ }
+ File current = file;
+ while (current != null) {
+ if (ancestors.contains(current)) {
+ return true;
+ }
+ current = FileUtilRt.getParentFile(current);
+ }
+ return false;
+ }
+
+ public static File urlToFile(String url) {
+ return new File(FileUtilRt.toSystemDependentName(urlToPath(url)));
+ }
+
+ public static String urlToPath(String url) {
+ if (url == null) return null;
+ if (url.startsWith("file://")) {
+ return url.substring("file://".length());
+ }
+ else if (url.startsWith("jar://")) {
+ url = url.substring("jar://".length());
+ if (url.endsWith("!/")) {
+ url = url.substring(0, url.length() - "!/".length());
+ }
+ }
+ return url;
+ }
+
+ //todo[nik] copied from VfsUtil
+ @NotNull
+ public static String fixURLforIDEA(@NotNull String url ) {
+ int idx = url.indexOf(":/");
+ if( idx >= 0 && idx+2 < url.length() && url.charAt(idx+2) != '/' ) {
+ String prefix = url.substring(0, idx);
+ String suffix = url.substring(idx+2);
+
+ if (SystemInfoRt.isWindows) {
+ url = prefix+"://"+suffix;
+ } else {
+ url = prefix+":///"+suffix;
+ }
+ }
+ return url;
+ }
+
+ public static String pathToUrl(String path) {
+ return "file://" + path;
+ }
+
+ public static String getLibraryRootUrl(File file) {
+ String path = FileUtilRt.toSystemIndependentName(file.getAbsolutePath());
+ if (file.isDirectory()) {
+ return "file://" + path;
+ }
+ return "jar://" + path + "!/";
+ }
+}
diff --git a/jps/model-impl/jps-model-impl.iml b/jps/model-impl/jps-model-impl.iml
new file mode 100644
index 000000000000..4a17b3a41db1
--- /dev/null
+++ b/jps/model-impl/jps-model-impl.iml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ </component>
+</module>
+
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsElementFactory b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsElementFactory
new file mode 100644
index 000000000000..2053df115032
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsElementFactory
@@ -0,0 +1 @@
+org.jetbrains.jps.model.impl.JpsElementFactoryImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsEncodingConfigurationService b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsEncodingConfigurationService
new file mode 100644
index 000000000000..abc8f316edcc
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.JpsEncodingConfigurationService
@@ -0,0 +1 @@
+org.jetbrains.jps.model.impl.JpsEncodingConfigurationServiceImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService
new file mode 100644
index 000000000000..0313eb7ef3a3
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService
@@ -0,0 +1 @@
+org.jetbrains.jps.model.artifact.impl.JpsArtifactServiceImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory
new file mode 100644
index 000000000000..bbc28002f730
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory
@@ -0,0 +1 @@
+org.jetbrains.jps.model.artifact.impl.elements.JpsPackagingElementFactoryImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.ex.JpsExElementFactory b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.ex.JpsExElementFactory
new file mode 100644
index 000000000000..32e0e7de3d7d
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.ex.JpsExElementFactory
@@ -0,0 +1 @@
+org.jetbrains.jps.model.impl.JpsExElementFactoryImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JdkVersionDetector b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JdkVersionDetector
new file mode 100644
index 000000000000..86310023aac4
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JdkVersionDetector
@@ -0,0 +1 @@
+org.jetbrains.jps.model.java.impl.JdkVersionDetectorImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JpsJavaExtensionService b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JpsJavaExtensionService
new file mode 100644
index 000000000000..3d58916622f6
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.java.JpsJavaExtensionService
@@ -0,0 +1 @@
+org.jetbrains.jps.model.java.impl.JpsJavaExtensionServiceImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.JpsServiceManager b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.JpsServiceManager
new file mode 100644
index 000000000000..6e703605a384
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.JpsServiceManager
@@ -0,0 +1 @@
+org.jetbrains.jps.service.impl.JpsServiceManagerImpl \ No newline at end of file
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.SharedThreadPool b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.SharedThreadPool
new file mode 100644
index 000000000000..ee4528a7664f
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.service.SharedThreadPool
@@ -0,0 +1 @@
+org.jetbrains.jps.service.impl.SharedThreadPoolImpl \ No newline at end of file
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java
new file mode 100644
index 000000000000..47bbae834794
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+import org.jetbrains.jps.model.artifact.elements.JpsArchivePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactImpl<P extends JpsElement> extends JpsNamedCompositeElementBase<JpsArtifactImpl<P>> implements JpsArtifact {
+ private static final JpsElementChildRole<JpsCompositePackagingElement>
+ ROOT_ELEMENT_CHILD_ROLE = JpsElementChildRoleBase.create("root element");
+ private final JpsArtifactType<P> myArtifactType;
+ private String myOutputPath;
+ private boolean myBuildOnMake;
+
+
+ public JpsArtifactImpl(@NotNull String name, @NotNull JpsCompositePackagingElement rootElement, @NotNull JpsArtifactType<P> type, @NotNull P properties) {
+ super(name);
+ myArtifactType = type;
+ myContainer.setChild(ROOT_ELEMENT_CHILD_ROLE, rootElement);
+ myContainer.setChild(type.getPropertiesRole(), properties);
+ }
+
+ private JpsArtifactImpl(JpsArtifactImpl<P> original) {
+ super(original);
+ myArtifactType = original.myArtifactType;
+ myOutputPath = original.myOutputPath;
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactImpl<P> createCopy() {
+ return new JpsArtifactImpl<P>(this);
+ }
+
+ public String getOutputPath() {
+ return myOutputPath;
+ }
+
+ public void setOutputPath(@Nullable String outputPath) {
+ if (!Comparing.equal(myOutputPath, outputPath)) {
+ myOutputPath = outputPath;
+ fireElementChanged();
+ }
+ }
+
+ @Nullable
+ @Override
+ public String getOutputFilePath() {
+ if (StringUtil.isEmpty(myOutputPath)) return null;
+ JpsCompositePackagingElement root = getRootElement();
+ return root instanceof JpsArchivePackagingElement ? myOutputPath + "/" + ((JpsArchivePackagingElement)root).getArchiveName() : myOutputPath;
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactType<P> getArtifactType() {
+ return myArtifactType;
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactReferenceImpl createReference() {
+ return new JpsArtifactReferenceImpl(getName());
+ }
+
+ @NotNull
+ @Override
+ public JpsCompositePackagingElement getRootElement() {
+ return myContainer.getChild(ROOT_ELEMENT_CHILD_ROLE);
+ }
+
+ @Override
+ public void setRootElement(@NotNull JpsCompositePackagingElement rootElement) {
+ myContainer.setChild(ROOT_ELEMENT_CHILD_ROLE, rootElement);
+ }
+
+ @Override
+ public P getProperties() {
+ return myContainer.getChild(myArtifactType.getPropertiesRole());
+ }
+
+ @Override
+ public boolean isBuildOnMake() {
+ return myBuildOnMake;
+ }
+
+ @Override
+ public void setBuildOnMake(boolean buildOnMake) {
+ if (myBuildOnMake != buildOnMake) {
+ myBuildOnMake = buildOnMake;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java
new file mode 100644
index 000000000000..9469432a1433
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+import org.jetbrains.jps.model.impl.JpsNamedElementReferenceImpl;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactReferenceImpl extends JpsNamedElementReferenceImpl<JpsArtifact,JpsArtifactReferenceImpl> implements JpsArtifactReference {
+ public JpsArtifactReferenceImpl(@NotNull String artifactName) {
+ super(JpsArtifactRole.ARTIFACT_COLLECTION_ROLE, artifactName, JpsElementFactory.getInstance().createProjectReference());
+ }
+
+ private JpsArtifactReferenceImpl(JpsArtifactReferenceImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactReferenceImpl createCopy() {
+ return new JpsArtifactReferenceImpl(this);
+ }
+
+ @NotNull
+ @Override
+ public String getArtifactName() {
+ return myElementName;
+ }
+
+ @Override
+ public JpsArtifactReferenceImpl asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java
new file mode 100644
index 000000000000..d497455e0fd9
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl;
+
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+/**
+* @author nik
+*/
+public class JpsArtifactRole extends JpsElementChildRoleBase<JpsArtifact> {
+ public static final JpsArtifactRole INSTANCE = new JpsArtifactRole();
+ public static final JpsElementCollectionRole<JpsArtifact> ARTIFACT_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE);
+
+ public JpsArtifactRole() {
+ super("artifact");
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java
new file mode 100644
index 000000000000..7e3653c4712d
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactServiceImpl extends JpsArtifactService {
+
+ @Override
+ public List<JpsArtifact> getArtifacts(@NotNull JpsProject project) {
+ JpsElementCollection<JpsArtifact> collection = project.getContainer().getChild(JpsArtifactRole.ARTIFACT_COLLECTION_ROLE);
+ return collection != null ? collection.getElements() : Collections.<JpsArtifact>emptyList();
+ }
+
+ @Override
+ public List<JpsArtifact> getSortedArtifacts(@NotNull JpsProject project) {
+ List<JpsArtifact> artifacts = new ArrayList<JpsArtifact>(getArtifacts(project));
+ Collections.sort(artifacts, new Comparator<JpsArtifact>() {
+ @Override
+ public int compare(JpsArtifact o1, JpsArtifact o2) {
+ return o1.getName().compareToIgnoreCase(o2.getName());
+ }
+ });
+ return artifacts;
+ }
+
+ @Override
+ public <P extends JpsElement> JpsArtifact addArtifact(@NotNull JpsProject project,
+ @NotNull String name,
+ @NotNull JpsCompositePackagingElement rootElement,
+ @NotNull JpsArtifactType<P> type,
+ @NotNull P properties) {
+ JpsArtifact artifact = createArtifact(name, rootElement, type, properties);
+ return project.getContainer().getOrSetChild(JpsArtifactRole.ARTIFACT_COLLECTION_ROLE).addChild(artifact);
+ }
+
+
+ @Override
+ public <P extends JpsElement> JpsArtifact createArtifact(@NotNull String name, @NotNull JpsCompositePackagingElement rootElement,
+ @NotNull JpsArtifactType<P> type, @NotNull P properties) {
+ return new JpsArtifactImpl<P>(name, rootElement, type, properties);
+ }
+
+ @Override
+ public JpsArtifactReference createReference(@NotNull String artifactName) {
+ return new JpsArtifactReferenceImpl(artifactName);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java
new file mode 100644
index 000000000000..361a8f4db7ac
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsArchivePackagingElement;
+
+/**
+ * @author nik
+ */
+public class JpsArchivePackagingElementImpl extends JpsCompositePackagingElementBase<JpsArchivePackagingElementImpl>
+ implements JpsArchivePackagingElement {
+ private String myArchiveName;
+
+ public JpsArchivePackagingElementImpl(String archiveName) {
+ myArchiveName = archiveName;
+ }
+
+ private JpsArchivePackagingElementImpl(JpsArchivePackagingElementImpl original) {
+ super(original);
+ myArchiveName = original.myArchiveName;
+ }
+
+ @NotNull
+ @Override
+ public JpsArchivePackagingElementImpl createCopy() {
+ return new JpsArchivePackagingElementImpl(this);
+ }
+
+ @Override
+ public String getArchiveName() {
+ return myArchiveName;
+ }
+
+ @Override
+ public void setArchiveName(String directoryName) {
+ if (!myArchiveName.equals(directoryName)) {
+ myArchiveName = directoryName;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java
new file mode 100644
index 000000000000..d8a22c8ef3d1
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactRootElement;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.ex.JpsComplexPackagingElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactOutputPackagingElementImpl extends JpsComplexPackagingElementBase<JpsArtifactOutputPackagingElementImpl>
+ implements JpsArtifactOutputPackagingElement {
+ private static final JpsElementChildRole<JpsArtifactReference>
+ ARTIFACT_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("artifact reference");
+
+ public JpsArtifactOutputPackagingElementImpl(@NotNull JpsArtifactReference reference) {
+ myContainer.setChild(ARTIFACT_REFERENCE_CHILD_ROLE, reference);
+ }
+
+ private JpsArtifactOutputPackagingElementImpl(JpsArtifactOutputPackagingElementImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactOutputPackagingElementImpl createCopy() {
+ return new JpsArtifactOutputPackagingElementImpl(this);
+ }
+
+ @Override
+ @NotNull
+ public JpsArtifactReference getArtifactReference() {
+ return myContainer.getChild(ARTIFACT_REFERENCE_CHILD_ROLE);
+ }
+
+ @Override
+ public List<JpsPackagingElement> getSubstitution() {
+ JpsArtifact artifact = getArtifactReference().resolve();
+ if (artifact == null) return Collections.emptyList();
+ JpsCompositePackagingElement rootElement = artifact.getRootElement();
+ if (rootElement instanceof JpsArtifactRootElement) {
+ return new ArrayList<JpsPackagingElement>(rootElement.getChildren());
+ }
+ else {
+ return Collections.<JpsPackagingElement>singletonList(rootElement);
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java
new file mode 100644
index 000000000000..17d7bf63de51
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactRootElement;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactRootElementImpl extends JpsCompositePackagingElementBase<JpsArtifactRootElementImpl> implements JpsArtifactRootElement {
+ public JpsArtifactRootElementImpl() {
+ }
+
+ private JpsArtifactRootElementImpl(JpsArtifactRootElementImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsArtifactRootElementImpl createCopy() {
+ return new JpsArtifactRootElementImpl();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java
new file mode 100644
index 000000000000..cf43d5ef764f
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsCompositePackagingElementBase<Self extends JpsCompositePackagingElementBase<Self>> extends JpsCompositeElementBase<Self>
+ implements JpsCompositePackagingElement {
+ private static final JpsElementCollectionRole<JpsPackagingElement> CHILDREN_ROLE = JpsElementCollectionRole.create(JpsElementChildRoleBase.<JpsPackagingElement>create("child"));
+
+ protected JpsCompositePackagingElementBase() {
+ myContainer.setChild(CHILDREN_ROLE);
+ }
+
+ protected JpsCompositePackagingElementBase(JpsCompositePackagingElementBase<Self> original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public List<JpsPackagingElement> getChildren() {
+ return myContainer.getChild(CHILDREN_ROLE).getElements();
+ }
+
+
+ @Override
+ public <E extends JpsPackagingElement> E addChild(@NotNull E child) {
+ return myContainer.getChild(CHILDREN_ROLE).addChild(child);
+ }
+
+ @Override
+ public void removeChild(@NotNull JpsPackagingElement child) {
+ myContainer.getChild(CHILDREN_ROLE).removeChild(child);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java
new file mode 100644
index 000000000000..28e22d98d121
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsDirectoryCopyPackagingElement;
+
+/**
+ * @author nik
+ */
+public class JpsDirectoryCopyPackagingElementImpl extends JpsFileCopyPackagingElementBase<JpsDirectoryCopyPackagingElementImpl>
+ implements JpsDirectoryCopyPackagingElement {
+ public JpsDirectoryCopyPackagingElementImpl(String directoryPath) {
+ super(directoryPath);
+ }
+
+ @NotNull
+ @Override
+ public JpsDirectoryCopyPackagingElementImpl createCopy() {
+ return new JpsDirectoryCopyPackagingElementImpl(myFilePath);
+ }
+
+ @Override
+ public String getDirectoryPath() {
+ return getFilePath();
+ }
+
+ @Override
+ public void setDirectoryPath(String path) {
+ setFilePath(path);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java
new file mode 100644
index 000000000000..0f5e619083f2
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsDirectoryPackagingElement;
+
+/**
+ * @author nik
+ */
+public class JpsDirectoryPackagingElementImpl extends JpsCompositePackagingElementBase<JpsDirectoryPackagingElementImpl> implements JpsDirectoryPackagingElement {
+ private String myDirectoryName;
+
+ public JpsDirectoryPackagingElementImpl(String directoryName) {
+ myDirectoryName = directoryName;
+ }
+
+ private JpsDirectoryPackagingElementImpl(JpsDirectoryPackagingElementImpl original) {
+ super(original);
+ myDirectoryName = original.myDirectoryName;
+ }
+
+ @NotNull
+ @Override
+ public JpsDirectoryPackagingElementImpl createCopy() {
+ return new JpsDirectoryPackagingElementImpl(this);
+ }
+
+ @Override
+ public String getDirectoryName() {
+ return myDirectoryName;
+ }
+
+ @Override
+ public void setDirectoryName(String directoryName) {
+ if (!myDirectoryName.equals(directoryName)) {
+ myDirectoryName = directoryName;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java
new file mode 100644
index 000000000000..95e03fa3bdb9
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsExtractedDirectoryPackagingElement;
+
+/**
+ * @author nik
+ */
+public class JpsExtractedDirectoryPackagingElementImpl extends JpsFileCopyPackagingElementBase<JpsExtractedDirectoryPackagingElementImpl>
+ implements JpsExtractedDirectoryPackagingElement {
+ private String myPathInJar;
+
+ public JpsExtractedDirectoryPackagingElementImpl(String filePath, String pathInJar) {
+ super(filePath);
+ myPathInJar = pathInJar;
+ }
+
+ @NotNull
+ @Override
+ public JpsExtractedDirectoryPackagingElementImpl createCopy() {
+ return new JpsExtractedDirectoryPackagingElementImpl(myFilePath, myPathInJar);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsExtractedDirectoryPackagingElementImpl modified) {
+ super.applyChanges(modified);
+ setPathInJar(modified.myPathInJar);
+ }
+
+ @Override
+ public String getPathInJar() {
+ return myPathInJar;
+ }
+
+ @Override
+ public void setPathInJar(String pathInJar) {
+ if (!Comparing.equal(myPathInJar, pathInJar)) {
+ myPathInJar = pathInJar;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java
new file mode 100644
index 000000000000..8822dc4d145a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+/**
+ * @author nik
+ */
+public abstract class JpsFileCopyPackagingElementBase<Self extends JpsFileCopyPackagingElementBase<Self>> extends JpsElementBase<Self> implements
+ JpsPackagingElement {
+ protected String myFilePath;
+
+ public JpsFileCopyPackagingElementBase(String filePath) {
+ myFilePath = filePath;
+ }
+
+ @Override
+ public void applyChanges(@NotNull Self modified) {
+ setFilePath(modified.myFilePath);
+ }
+
+ public String getFilePath() {
+ return myFilePath;
+ }
+
+ public void setFilePath(String filePath) {
+ if (!Comparing.equal(myFilePath, filePath)) {
+ myFilePath = filePath;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java
new file mode 100644
index 000000000000..f565fc32f246
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.elements.JpsFileCopyPackagingElement;
+
+/**
+ * @author nik
+ */
+public class JpsFileCopyPackagingElementImpl extends JpsFileCopyPackagingElementBase<JpsFileCopyPackagingElementImpl> implements JpsFileCopyPackagingElement {
+ private String myRenamedOutputFileName;
+
+ public JpsFileCopyPackagingElementImpl(String filePath, String renamedOutputFileName) {
+ super(filePath);
+ myRenamedOutputFileName = renamedOutputFileName;
+ }
+
+ @NotNull
+ @Override
+ public JpsFileCopyPackagingElementImpl createCopy() {
+ return new JpsFileCopyPackagingElementImpl(myFilePath, myRenamedOutputFileName);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsFileCopyPackagingElementImpl modified) {
+ super.applyChanges(modified);
+ setRenamedOutputFileName(modified.myRenamedOutputFileName);
+ }
+
+ @Override
+ public String getRenamedOutputFileName() {
+ return myRenamedOutputFileName;
+ }
+
+ @Override
+ public void setRenamedOutputFileName(String renamedOutputFileName) {
+ if (!Comparing.equal(myRenamedOutputFileName, renamedOutputFileName)) {
+ myRenamedOutputFileName = renamedOutputFileName;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java
new file mode 100644
index 000000000000..2931dbc11f8a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.artifact.elements.JpsLibraryFilesPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory;
+import org.jetbrains.jps.model.artifact.elements.ex.JpsComplexPackagingElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryFilesPackagingElementImpl extends JpsComplexPackagingElementBase<JpsLibraryFilesPackagingElementImpl> implements JpsLibraryFilesPackagingElement {
+ private static final JpsElementChildRole<JpsLibraryReference>
+ LIBRARY_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("library reference");
+
+ public JpsLibraryFilesPackagingElementImpl(@NotNull JpsLibraryReference reference) {
+ myContainer.setChild(LIBRARY_REFERENCE_CHILD_ROLE, reference);
+ }
+
+ private JpsLibraryFilesPackagingElementImpl(JpsLibraryFilesPackagingElementImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryFilesPackagingElementImpl createCopy() {
+ return new JpsLibraryFilesPackagingElementImpl(this);
+ }
+
+ @Override
+ @NotNull
+ public JpsLibraryReference getLibraryReference() {
+ return myContainer.getChild(LIBRARY_REFERENCE_CHILD_ROLE);
+ }
+
+ @Override
+ public List<JpsPackagingElement> getSubstitution() {
+ JpsLibrary library = getLibraryReference().resolve();
+ if (library == null) return Collections.emptyList();
+ List<JpsPackagingElement> result = new ArrayList<JpsPackagingElement>();
+ for (File file : library.getFiles(JpsOrderRootType.COMPILED)) {
+ String path = FileUtil.toSystemIndependentName(file.getAbsolutePath());
+ if (file.isDirectory()) {
+ result.add(JpsPackagingElementFactory.getInstance().createDirectoryCopy(path));
+ }
+ else {
+ result.add(JpsPackagingElementFactory.getInstance().createFileCopy(path, null));
+ }
+ }
+ return result;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java
new file mode 100644
index 000000000000..b3342f81bee8
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModuleOutputPackagingElementBase<Self extends JpsModuleOutputPackagingElementBase<Self>> extends JpsCompositeElementBase<Self> implements
+ JpsModuleOutputPackagingElement {
+ private static final JpsElementChildRole<JpsModuleReference>
+ MODULE_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("module reference");
+
+ public JpsModuleOutputPackagingElementBase(JpsModuleReference moduleReference) {
+ myContainer.setChild(MODULE_REFERENCE_CHILD_ROLE, moduleReference);
+ }
+
+ public JpsModuleOutputPackagingElementBase(JpsModuleOutputPackagingElementBase<Self> original) {
+ super(original);
+ }
+
+ @Override
+ @NotNull
+ public JpsModuleReference getModuleReference() {
+ return myContainer.getChild(MODULE_REFERENCE_CHILD_ROLE);
+ }
+
+ @Override
+ @Nullable
+ public String getOutputUrl() {
+ JpsModule module = getModuleReference().resolve();
+ if (module == null) return null;
+ return getOutputUrl(module);
+ }
+
+ @Nullable
+ protected abstract String getOutputUrl(@NotNull JpsModule module);
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java
new file mode 100644
index 000000000000..8c023c3ca997
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.artifact.impl.elements;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.artifact.JpsArtifactReference;
+import org.jetbrains.jps.model.artifact.elements.*;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+
+/**
+ * @author nik
+ */
+public class JpsPackagingElementFactoryImpl extends JpsPackagingElementFactory {
+
+ @Override
+ @NotNull
+ public JpsDirectoryCopyPackagingElement createDirectoryCopy(@NotNull String directoryPath) {
+ return new JpsDirectoryCopyPackagingElementImpl(directoryPath);
+ }
+
+ @Override
+ public JpsPackagingElement createParentDirectories(String relativeOutputPath, JpsPackagingElement element) {
+ relativeOutputPath = StringUtil.trimStart(relativeOutputPath, "/");
+ if (relativeOutputPath.length() == 0) {
+ return element;
+ }
+ int slash = relativeOutputPath.indexOf('/');
+ if (slash == -1) slash = relativeOutputPath.length();
+ String rootName = relativeOutputPath.substring(0, slash);
+ String pathTail = relativeOutputPath.substring(slash);
+ final JpsDirectoryPackagingElement root = createDirectory(rootName);
+ final JpsCompositePackagingElement last = getOrCreateDirectoryOrArchive(root, pathTail, true);
+ last.addChild(element);
+ return root;
+ }
+
+ @Override
+ public JpsCompositePackagingElement getOrCreateDirectory(@NotNull JpsCompositePackagingElement root, @NotNull String path) {
+ return getOrCreateDirectoryOrArchive(root, path, true);
+ }
+
+ @Override
+ public JpsCompositePackagingElement getOrCreateArchive(@NotNull JpsCompositePackagingElement root, @NotNull String path) {
+ return getOrCreateDirectoryOrArchive(root, path, false);
+ }
+
+ @NotNull
+ private JpsCompositePackagingElement getOrCreateDirectoryOrArchive(@NotNull JpsCompositePackagingElement root,
+ @NotNull @NonNls String path, final boolean directory) {
+ path = StringUtil.trimStart(StringUtil.trimEnd(path, "/"), "/");
+ if (path.length() == 0) {
+ return root;
+ }
+ int index = path.lastIndexOf('/');
+ String lastName = path.substring(index + 1);
+ String parentPath = index != -1 ? path.substring(0, index) : "";
+
+ final JpsCompositePackagingElement parent = getOrCreateDirectoryOrArchive(root, parentPath, true);
+ final JpsCompositePackagingElement last = directory ? createDirectory(lastName) : createArchive(lastName);
+ return parent.addChild(last);
+ }
+
+ @Override
+ @NotNull
+ public JpsFileCopyPackagingElement createFileCopy(@NotNull String filePath, @Nullable String outputFileName) {
+ return new JpsFileCopyPackagingElementImpl(filePath, outputFileName);
+ }
+
+ @Override
+ @NotNull
+ public JpsExtractedDirectoryPackagingElement createExtractedDirectory(@NotNull String jarPath, @NotNull String pathInJar) {
+ return new JpsExtractedDirectoryPackagingElementImpl(jarPath, pathInJar);
+ }
+
+ @Override
+ @NotNull
+ public JpsDirectoryPackagingElement createDirectory(@NotNull String directoryName) {
+ return new JpsDirectoryPackagingElementImpl(directoryName);
+ }
+
+ @Override
+ @NotNull
+ public JpsArchivePackagingElement createArchive(@NotNull String archiveName) {
+ return new JpsArchivePackagingElementImpl(archiveName);
+ }
+
+ @Override
+ @NotNull
+ public JpsArtifactRootElement createArtifactRoot() {
+ return new JpsArtifactRootElementImpl();
+ }
+
+ @Override
+ @NotNull
+ public JpsLibraryFilesPackagingElement createLibraryElement(@NotNull JpsLibraryReference reference) {
+ return new JpsLibraryFilesPackagingElementImpl(reference);
+ }
+
+ @Override
+ @NotNull
+ public JpsArtifactOutputPackagingElement createArtifactOutput(@NotNull JpsArtifactReference reference) {
+ return new JpsArtifactOutputPackagingElementImpl(reference);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/ex/JpsElementContainerImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/ex/JpsElementContainerImpl.java
new file mode 100644
index 000000000000..6f0ae68c0ff4
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/ex/JpsElementContainerImpl.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.ex;
+
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsElementContainerImpl extends JpsElementContainerEx implements JpsElementContainer {
+ private final Map<JpsElementChildRole<?>, JpsElement> myElements = new THashMap<JpsElementChildRole<?>, JpsElement>(1);
+ private final @NotNull JpsCompositeElementBase<?> myParent;
+
+ public JpsElementContainerImpl(@NotNull JpsCompositeElementBase<?> parent) {
+ myParent = parent;
+ }
+
+ public JpsElementContainerImpl(@NotNull JpsElementContainerEx original, @NotNull JpsCompositeElementBase<?> parent) {
+ myParent = parent;
+ for (Map.Entry<JpsElementChildRole<?>, JpsElement> entry : original.getElementsMap().entrySet()) {
+ final JpsElementChildRole role = entry.getKey();
+ final JpsElement copy = entry.getValue().getBulkModificationSupport().createCopy();
+ JpsElementBase.setParent(copy, myParent);
+ myElements.put(role, copy);
+ }
+ }
+
+ @Override
+ public <T extends JpsElement> T getChild(@NotNull JpsElementChildRole<T> role) {
+ //noinspection unchecked
+ return (T)myElements.get(role);
+ }
+
+ @NotNull
+ @Override
+ public <T extends JpsElement, P, K extends JpsElementChildRole<T> & JpsElementParameterizedCreator<T, P>> T setChild(@NotNull K role,
+ @NotNull P param) {
+ final T child = role.create(param);
+ return setChild(role, child);
+ }
+
+ @NotNull
+ @Override
+ public <T extends JpsElement, K extends JpsElementChildRole<T> & JpsElementCreator<T>> T setChild(@NotNull K role) {
+ final T child = role.create();
+ return setChild(role, child);
+ }
+
+ @NotNull
+ @Override
+ public <T extends JpsElement, K extends JpsElementChildRole<T> & JpsElementCreator<T>> T getOrSetChild(@NotNull K role) {
+ final T child = getChild(role);
+ if (child == null) {
+ return setChild(role);
+ }
+ return child;
+ }
+
+ @Override
+ public <T extends JpsElement> T setChild(JpsElementChildRole<T> role, T child) {
+ myElements.put(role, child);
+ JpsElementBase.setParent(child, myParent);
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementAdded(child, role);
+ }
+ return child;
+ }
+
+ @Override
+ public <T extends JpsElement> void removeChild(@NotNull JpsElementChildRole<T> role) {
+ //noinspection unchecked
+ final T removed = (T)myElements.remove(role);
+ if (removed == null) return;
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementRemoved(removed, role);
+ }
+ JpsElementBase.setParent(removed, null);
+ }
+
+ @Override
+ protected Map<JpsElementChildRole<?>, JpsElement> getElementsMap() {
+ return myElements;
+ }
+
+ public void applyChanges(@NotNull JpsElementContainerEx modified) {
+ for (JpsElementChildRole<?> role : myElements.keySet()) {
+ applyChanges(role, modified);
+ }
+ for (JpsElementChildRole<?> role : modified.getElementsMap().keySet()) {
+ if (!myElements.containsKey(role)) {
+ applyChanges(role, modified);
+ }
+ }
+ }
+
+ private <T extends JpsElement> void applyChanges(JpsElementChildRole<T> role, JpsElementContainerEx modified) {
+ final T child = getChild(role);
+ final T modifiedChild = modified.getChild(role);
+ if (child != null && modifiedChild != null) {
+ final JpsElement.BulkModificationSupport modificationSupport = child.getBulkModificationSupport();
+ //noinspection unchecked
+ modificationSupport.applyChanges(modifiedChild);
+ }
+ else if (modifiedChild == null) {
+ removeChild(role);
+ }
+ else {
+ //noinspection unchecked
+ setChild(role, (T)modifiedChild.getBulkModificationSupport().createCopy());
+ }
+ }
+
+ @Nullable
+ private JpsEventDispatcher getEventDispatcher() {
+ return myParent.getEventDispatcher();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsDummyElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsDummyElementImpl.java
new file mode 100644
index 000000000000..a18689557623
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsDummyElementImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+/**
+ * @author nik
+ */
+public class JpsDummyElementImpl extends JpsElementBase<JpsDummyElementImpl> implements JpsDummyElement {
+ @NotNull
+ @Override
+ public JpsDummyElementImpl createCopy() {
+ return new JpsDummyElementImpl();
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsDummyElementImpl modified) {
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java
new file mode 100644
index 000000000000..49bef127a229
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.FilteringIterator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JpsElementCollectionImpl<E extends JpsElement> extends JpsElementBase<JpsElementCollectionImpl<E>> implements JpsElementCollection<E> {
+ private final List<E> myElements;
+ private final Map<E, E> myCopyToOriginal;
+ private final JpsElementChildRole<E> myChildRole;
+
+ JpsElementCollectionImpl(JpsElementChildRole<E> role) {
+ myChildRole = role;
+ myElements = new SmartList<E>();
+ myCopyToOriginal = null;
+ }
+
+ private JpsElementCollectionImpl(JpsElementCollectionImpl<E> original) {
+ myChildRole = original.myChildRole;
+ myElements = new SmartList<E>();
+ myCopyToOriginal = new HashMap<E, E>();
+ for (E e : original.myElements) {
+ //noinspection unchecked
+ final E copy = (E)e.getBulkModificationSupport().createCopy();
+ setParent(copy, this);
+ myElements.add(copy);
+ myCopyToOriginal.put(copy, e);
+ }
+ }
+
+ @Override
+ public List<E> getElements() {
+ return myElements;
+ }
+
+ @Override
+ public <X extends JpsTypedElement<P>, P extends JpsElement> Iterable<X> getElementsOfType(@NotNull final JpsElementType<P> type) {
+ return new JpsElementIterable<X, P>(type);
+ }
+
+ @NotNull
+ @Override
+ public E addChild(@NotNull JpsElementCreator<E> creator) {
+ return addChild(creator.create());
+ }
+
+ @Override
+ public <X extends E> X addChild(X element) {
+ myElements.add(element);
+ setParent(element, this);
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementAdded(element, myChildRole);
+ }
+ return element;
+ }
+
+ @Override
+ public void removeChild(@NotNull E element) {
+ final boolean removed = myElements.remove(element);
+ if (removed) {
+ final JpsEventDispatcher eventDispatcher = getEventDispatcher();
+ if (eventDispatcher != null) {
+ eventDispatcher.fireElementRemoved(element, myChildRole);
+ }
+ setParent(element, null);
+ }
+ }
+
+ @Override
+ public void removeAllChildren() {
+ List<E> elements = new ArrayList<E>(myElements);
+ for (E element : elements) {
+ removeChild(element);
+ }
+ }
+
+ @NotNull
+ @Override
+ public JpsElementCollectionImpl<E> createCopy() {
+ return new JpsElementCollectionImpl<E>(this);
+ }
+
+ public void applyChanges(@NotNull JpsElementCollectionImpl<E> modified) {
+ Set<E> toRemove = new LinkedHashSet<E>(myElements);
+ List<E> toAdd = new ArrayList<E>();
+ final Map<E, E> copyToOriginal = modified.myCopyToOriginal;
+ for (E element : modified.myElements) {
+ final E original = copyToOriginal != null ? copyToOriginal.get(element) : null;
+ if (original != null) {
+ //noinspection unchecked
+ ((BulkModificationSupport<E>)original.getBulkModificationSupport()).applyChanges(element);
+ toRemove.remove(original);
+ }
+ else {
+ //noinspection unchecked
+ final E copy = (E)element.getBulkModificationSupport().createCopy();
+ toAdd.add(copy);
+ }
+ }
+ for (E e : toRemove) {
+ removeChild(e);
+ }
+ for (E e : toAdd) {
+ addChild(e);
+ }
+ }
+
+ private class JpsElementIterable<X extends JpsTypedElement<P>, P extends JpsElement> implements Iterable<X> {
+ private final JpsElementType<? extends JpsElement> myType;
+
+ public JpsElementIterable(JpsElementType<P> type) {
+ myType = type;
+ }
+
+ @Override
+ public Iterator<X> iterator() {
+ //noinspection unchecked
+ Iterator<JpsTypedElement<?>> iterator = (Iterator<JpsTypedElement<?>>)myElements.iterator();
+ return new FilteringIterator<JpsTypedElement<?>, X>(iterator, new Condition<JpsTypedElement<?>>() {
+ @Override
+ public boolean value(JpsTypedElement<?> e) {
+ return e.getType().equals(myType);
+ }
+ });
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java
new file mode 100644
index 000000000000..9876c6c3db55
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.impl.JpsLibraryImpl;
+import org.jetbrains.jps.model.library.impl.JpsLibraryReferenceImpl;
+import org.jetbrains.jps.model.library.impl.JpsSdkReferenceImpl;
+import org.jetbrains.jps.model.library.impl.sdk.JpsSdkImpl;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.model.module.impl.JpsModuleImpl;
+import org.jetbrains.jps.model.module.impl.JpsModuleReferenceImpl;
+
+/**
+ * @author nik
+ */
+public class JpsElementFactoryImpl extends JpsElementFactory {
+ @Override
+ public JpsModel createModel() {
+ return new JpsModelImpl(new JpsEventDispatcherBase() {
+ @Override
+ public void fireElementRenamed(@NotNull JpsNamedElement element, @NotNull String oldName, @NotNull String newName) {
+ }
+
+ @Override
+ public void fireElementChanged(@NotNull JpsElement element) {
+ }
+ });
+ }
+
+ @Override
+ public <P extends JpsElement> JpsModule createModule(@NotNull String name, @NotNull JpsModuleType<P> type, @NotNull P properties) {
+ return new JpsModuleImpl<P>(type, name, properties);
+ }
+
+
+ @Override
+ public <P extends JpsElement> JpsTypedLibrary<P> createLibrary(@NotNull String name,
+ @NotNull JpsLibraryType<P> type,
+ @NotNull P properties) {
+ return new JpsLibraryImpl<P>(name, type, properties);
+ }
+
+ @Override
+ public <P extends JpsElement> JpsTypedLibrary<JpsSdk<P>> createSdk(@NotNull String name, @Nullable String homePath,
+ @Nullable String versionString, @NotNull JpsSdkType<P> type,
+ @NotNull P properties) {
+ return createLibrary(name, type, new JpsSdkImpl<P>(homePath, versionString, type, properties));
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleReference createModuleReference(@NotNull String moduleName) {
+ return new JpsModuleReferenceImpl(moduleName);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryReference createLibraryReference(@NotNull String libraryName,
+ @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
+ return new JpsLibraryReferenceImpl(libraryName, parentReference);
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> JpsSdkReference<P> createSdkReference(@NotNull String sdkName, @NotNull JpsSdkType<P> sdkType) {
+ return new JpsSdkReferenceImpl<P>(sdkName, sdkType, createGlobalReference());
+ }
+
+ @NotNull
+ @Override
+ public JpsElementReference<JpsProject> createProjectReference() {
+ return new JpsProjectElementReference();
+ }
+
+ @NotNull
+ @Override
+ public JpsElementReference<JpsGlobal> createGlobalReference() {
+ return new JpsGlobalElementReference();
+ }
+
+ @NotNull
+ @Override
+ public JpsDummyElement createDummyElement() {
+ return new JpsDummyElementImpl();
+ }
+
+ @NotNull
+ @Override
+ public <D> JpsSimpleElement<D> createSimpleElement(@NotNull D data) {
+ return new JpsSimpleElementImpl<D>(data);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingConfigurationServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingConfigurationServiceImpl.java
new file mode 100644
index 000000000000..f0c06add5a4f
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingConfigurationServiceImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsEncodingConfigurationServiceImpl extends JpsEncodingConfigurationService {
+ private static final JpsElementChildRoleBase<JpsSimpleElement<String>> ENCODING_ROLE = JpsElementChildRoleBase.create("encoding");
+
+ @Nullable
+ @Override
+ public String getGlobalEncoding(@NotNull JpsGlobal global) {
+ JpsSimpleElement<String> encoding = global.getContainer().getChild(ENCODING_ROLE);
+ return encoding != null ? encoding.getData() : null;
+ }
+
+ @Override
+ public void setGlobalEncoding(@NotNull JpsGlobal global, @Nullable String encoding) {
+ if (encoding != null) {
+ global.getContainer().setChild(ENCODING_ROLE, JpsElementFactory.getInstance().createSimpleElement(encoding));
+ }
+ else {
+ global.getContainer().removeChild(ENCODING_ROLE);
+ }
+ }
+
+ @Nullable
+ @Override
+ public String getProjectEncoding(@NotNull JpsModel model) {
+ JpsEncodingProjectConfiguration configuration = getEncodingConfiguration(model.getProject());
+ if (configuration != null) {
+ String projectEncoding = configuration.getProjectEncoding();
+ if (projectEncoding != null) {
+ return projectEncoding;
+ }
+ }
+ return getGlobalEncoding(model.getGlobal());
+ }
+
+ @Nullable
+ @Override
+ public JpsEncodingProjectConfiguration getEncodingConfiguration(@NotNull JpsProject project) {
+ return project.getContainer().getChild(JpsEncodingProjectConfigurationImpl.ROLE);
+ }
+
+ @NotNull
+ @Override
+ public JpsEncodingProjectConfiguration setEncodingConfiguration(@NotNull JpsProject project,
+ @Nullable String projectEncoding,
+ @NotNull Map<String, String> urlToEncoding) {
+ JpsEncodingProjectConfigurationImpl configuration = new JpsEncodingProjectConfigurationImpl(urlToEncoding, projectEncoding);
+ return project.getContainer().setChild(JpsEncodingProjectConfigurationImpl.ROLE, configuration);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingProjectConfigurationImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingProjectConfigurationImpl.java
new file mode 100644
index 000000000000..1b7ce68c8277
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEncodingProjectConfigurationImpl.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.text.XmlCharsetDetector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsEncodingProjectConfigurationImpl extends JpsElementBase<JpsEncodingProjectConfigurationImpl>
+ implements JpsEncodingProjectConfiguration {
+ private static final Logger LOG = Logger.getInstance(JpsEncodingProjectConfigurationImpl.class);
+ public static final JpsElementChildRole<JpsEncodingProjectConfiguration> ROLE = JpsElementChildRoleBase.create("encoding configuration");
+ private static final String XML_NAME_SUFFIX = ".xml";
+ private final Map<String, String> myUrlToEncoding = new HashMap<String, String>();
+ private final String myProjectEncoding;
+
+ public JpsEncodingProjectConfigurationImpl(Map<String, String> urlToEncoding, String projectEncoding) {
+ myUrlToEncoding.putAll(urlToEncoding);
+ myProjectEncoding = projectEncoding;
+ }
+
+ @Nullable
+ @Override
+ public String getEncoding(@NotNull File file) {
+ if (isXmlFile(file)) {
+ try {
+ String encoding = XmlCharsetDetector.extractXmlEncodingFromProlog(FileUtil.loadFileBytes(file));
+ if (encoding != null) {
+ return encoding;
+ }
+ }
+ catch (IOException e) {
+ LOG.info("Cannot detect encoding for xml file " + file.getAbsolutePath(), e);
+ }
+ }
+
+ if (!myUrlToEncoding.isEmpty()) {
+
+ File current = file;
+ while (current != null) {
+ String encoding = myUrlToEncoding.get(JpsPathUtil.pathToUrl(FileUtilRt.toSystemIndependentName(current.getPath())));
+
+ if (encoding != null) {
+ return encoding;
+ }
+
+ current = FileUtilRt.getParentFile(current);
+ }
+ }
+
+ if (myProjectEncoding != null) {
+ return myProjectEncoding;
+ }
+
+ final JpsModel model = getModel();
+ assert model != null;
+ return JpsEncodingConfigurationService.getInstance().getGlobalEncoding(model.getGlobal());
+ }
+
+ private static boolean isXmlFile(File file) {
+ String fileName = file.getName();
+ return SystemInfo.isFileSystemCaseSensitive ? fileName.endsWith(XML_NAME_SUFFIX) : StringUtil.endsWithIgnoreCase(fileName, XML_NAME_SUFFIX);
+ }
+
+ @NotNull
+ @Override
+ public Map<String, String> getUrlToEncoding() {
+ return Collections.unmodifiableMap(myUrlToEncoding);
+ }
+
+ @Nullable
+ @Override
+ public String getProjectEncoding() {
+ return myProjectEncoding;
+ }
+
+ @NotNull
+ @Override
+ public JpsEncodingProjectConfigurationImpl createCopy() {
+ return new JpsEncodingProjectConfigurationImpl(myUrlToEncoding, myProjectEncoding);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsEncodingProjectConfigurationImpl modified) {
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEventDispatcherBase.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEventDispatcherBase.java
new file mode 100644
index 000000000000..7226b3854069
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsEventDispatcherBase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import com.intellij.util.EventDispatcher;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public abstract class JpsEventDispatcherBase implements JpsEventDispatcher {
+ private Map<Class<?>, EventDispatcher<?>> myDispatchers = new HashMap<Class<?>, EventDispatcher<?>>();
+
+ @NotNull
+ @Override
+ public <T extends EventListener> T getPublisher(Class<T> listenerClass) {
+ EventDispatcher<?> dispatcher = myDispatchers.get(listenerClass);
+ if (dispatcher == null) {
+ dispatcher = EventDispatcher.create(listenerClass);
+ myDispatchers.put(listenerClass, dispatcher);
+ }
+ //noinspection unchecked
+ return (T)dispatcher.getMulticaster();
+ }
+
+ @Override
+ public <T extends JpsElement> void fireElementAdded(@NotNull T element, @NotNull JpsElementChildRole<T> role) {
+ role.fireElementAdded(this, element);
+ }
+
+ @Override
+ public <T extends JpsElement> void fireElementRemoved(@NotNull T element, @NotNull JpsElementChildRole<T> role) {
+ role.fireElementRemoved(this, element);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java
new file mode 100644
index 000000000000..c200af1efa6f
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementContainerEx;
+import org.jetbrains.jps.model.ex.JpsElementContainerImpl;
+import org.jetbrains.jps.model.ex.JpsExElementFactory;
+
+/**
+ * @author nik
+ */
+public class JpsExElementFactoryImpl extends JpsExElementFactory {
+ @Override
+ public JpsElementContainerEx createContainer(@NotNull JpsCompositeElementBase<?> parent) {
+ return new JpsElementContainerImpl(parent);
+ }
+
+ @Override
+ public JpsElementContainerEx createContainerCopy(@NotNull JpsElementContainerEx original,
+ @NotNull JpsCompositeElementBase<?> parent) {
+ return new JpsElementContainerImpl(original, parent);
+ }
+
+ @Override
+ public <E extends JpsElement> JpsElementCollection<E> createCollection(JpsElementChildRole<E> role) {
+ return new JpsElementCollectionImpl<E>(role);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsFileTypesConfigurationImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsFileTypesConfigurationImpl.java
new file mode 100644
index 000000000000..b1e0c2e6491f
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsFileTypesConfigurationImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsFileTypesConfiguration;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+/**
+ * @author nik
+ */
+public class JpsFileTypesConfigurationImpl extends JpsElementBase<JpsFileTypesConfigurationImpl> implements JpsFileTypesConfiguration {
+ public static final JpsElementChildRole<JpsFileTypesConfiguration> ROLE = JpsElementChildRoleBase.create("file types");
+ private String myIgnoredPatternString;
+
+ public JpsFileTypesConfigurationImpl() {
+ this("CVS;SCCS;RCS;rcs;.DS_Store;.svn;.pyc;.pyo;*.pyc;*.pyo;.git;*.hprof;_svn;.hg;*.lib;*~;__pycache__;.bundle;vssver.scc;vssver2.scc;*.rbc;");
+ }
+
+ private JpsFileTypesConfigurationImpl(String ignoredPatternString) {
+ myIgnoredPatternString = ignoredPatternString;
+ }
+
+ @NotNull
+ @Override
+ public JpsFileTypesConfigurationImpl createCopy() {
+ return new JpsFileTypesConfigurationImpl(myIgnoredPatternString);
+ }
+
+ @Override
+ public String getIgnoredPatternString() {
+ return myIgnoredPatternString;
+ }
+
+ @Override
+ public void setIgnoredPatternString(@NotNull String ignoredPatternString) {
+ if (!myIgnoredPatternString.equals(ignoredPatternString)) {
+ myIgnoredPatternString = ignoredPatternString;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsFileTypesConfigurationImpl modified) {
+ setIgnoredPatternString(modified.myIgnoredPatternString);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalElementReference.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalElementReference.java
new file mode 100644
index 000000000000..b67e723907bb
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalElementReference.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementReferenceBase;
+
+/**
+ * @author nik
+ */
+public class JpsGlobalElementReference extends JpsElementReferenceBase<JpsGlobalElementReference, JpsGlobal> {
+ @Override
+ public JpsGlobal resolve() {
+ final JpsModel model = getModel();
+ return model != null ? model.getGlobal() : null;
+ }
+
+ @NotNull
+ @Override
+ public JpsGlobalElementReference createCopy() {
+ return new JpsGlobalElementReference();
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsGlobalElementReference modified) {
+ }
+
+ @Override
+ public String toString() {
+ return "global ref";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalImpl.java
new file mode 100644
index 000000000000..61589ad95fbc
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsGlobalImpl.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.library.*;
+import org.jetbrains.jps.model.library.impl.JpsLibraryCollectionImpl;
+import org.jetbrains.jps.model.library.impl.JpsLibraryRole;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+/**
+ * @author nik
+ */
+public class JpsGlobalImpl extends JpsRootElementBase<JpsGlobalImpl> implements JpsGlobal {
+ private final JpsLibraryCollectionImpl myLibraryCollection;
+
+ public JpsGlobalImpl(@NotNull JpsModel model, JpsEventDispatcher eventDispatcher) {
+ super(model, eventDispatcher);
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.setChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ myContainer.setChild(JpsFileTypesConfigurationImpl.ROLE, new JpsFileTypesConfigurationImpl());
+ }
+
+ public JpsGlobalImpl(JpsGlobalImpl original, JpsModel model, JpsEventDispatcher eventDispatcher) {
+ super(original, model, eventDispatcher);
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ }
+
+ @NotNull
+ @Override
+ public
+ <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull LibraryType libraryType, @NotNull final String name) {
+ return myLibraryCollection.addLibrary(name, libraryType);
+ }
+
+ @Override
+ public <P extends JpsElement> JpsTypedLibrary<JpsSdk<P>> addSdk(@NotNull String name, @Nullable String homePath,
+ @Nullable String versionString, @NotNull JpsSdkType<P> type,
+ @NotNull P properties) {
+ JpsTypedLibrary<JpsSdk<P>> sdk = JpsElementFactory.getInstance().createSdk(name, homePath, versionString, type, properties);
+ myLibraryCollection.addLibrary(sdk);
+ return sdk;
+ }
+
+ @Override
+ public <P extends JpsElement, SdkType extends JpsSdkType<P> & JpsElementTypeWithDefaultProperties<P>> JpsTypedLibrary<JpsSdk<P>>
+ addSdk(@NotNull String name, @Nullable String homePath, @Nullable String versionString, @NotNull SdkType type) {
+ return addSdk(name, homePath, versionString, type, type.createDefaultProperties());
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryCollection getLibraryCollection() {
+ return myLibraryCollection;
+ }
+
+ @NotNull
+ @Override
+ public JpsFileTypesConfiguration getFileTypesConfiguration() {
+ return myContainer.getChild(JpsFileTypesConfigurationImpl.ROLE);
+ }
+
+ @NotNull
+ @Override
+ public JpsElementReference<JpsGlobal> createReference() {
+ return new JpsGlobalElementReference();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsModelImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsModelImpl.java
new file mode 100644
index 000000000000..f4459e5b1ef8
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsModelImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.JpsModel;
+
+/**
+ * @author nik
+ */
+public class JpsModelImpl implements JpsModel {
+ private JpsProjectImpl myProject;
+ private JpsGlobalImpl myGlobal;
+ private JpsModelImpl myOriginalModel;
+ private final JpsEventDispatcher myEventDispatcher;
+
+ public JpsModelImpl(JpsEventDispatcher eventDispatcher) {
+ myEventDispatcher = eventDispatcher;
+ myProject = new JpsProjectImpl(this, eventDispatcher);
+ myGlobal = new JpsGlobalImpl(this, eventDispatcher);
+ }
+
+ private JpsModelImpl(JpsModelImpl original, JpsEventDispatcher eventDispatcher) {
+ myOriginalModel = original;
+ myEventDispatcher = eventDispatcher;
+ myProject = new JpsProjectImpl(original.myProject, this, eventDispatcher);
+ myGlobal = new JpsGlobalImpl(original.myGlobal, this, eventDispatcher);
+ }
+
+ @NotNull
+ public JpsProjectImpl getProject() {
+ return myProject;
+ }
+
+ @NotNull
+ public JpsGlobalImpl getGlobal() {
+ return myGlobal;
+ }
+
+ @NotNull
+ @Override
+ public JpsModel createModifiableModel(@NotNull JpsEventDispatcher eventDispatcher) {
+ return new JpsModelImpl(this, eventDispatcher);
+ }
+
+ @Override
+ public void registerExternalReference(@NotNull JpsElementReference<?> reference) {
+ myProject.addExternalReference(reference);
+ }
+
+ @Override
+ public void commit() {
+ myOriginalModel.applyChanges(this);
+ }
+
+ private void applyChanges(@NotNull JpsModelImpl modifiedCopy) {
+ myProject.applyChanges(modifiedCopy.myProject);
+ myGlobal.applyChanges(modifiedCopy.myGlobal);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java
new file mode 100644
index 000000000000..3822a0d9128b
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsNamedElementReferenceBase<S extends JpsNamedElement, T extends JpsNamedElement, Self extends JpsNamedElementReferenceBase<S, T, Self>>
+ extends JpsCompositeElementBase<Self> implements JpsElementReference<T> {
+ private static final JpsElementChildRole<JpsElementReference<? extends JpsCompositeElement>> PARENT_REFERENCE_ROLE = JpsElementChildRoleBase
+ .create("parent");
+ protected final String myElementName;
+
+ protected JpsNamedElementReferenceBase(@NotNull String elementName, @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
+ myElementName = elementName;
+ myContainer.setChild(PARENT_REFERENCE_ROLE, parentReference);
+ }
+
+ protected JpsNamedElementReferenceBase(JpsNamedElementReferenceBase<S, T, Self> original) {
+ super(original);
+ myElementName = original.myElementName;
+ }
+
+ @Override
+ public T resolve() {
+ final JpsCompositeElement parent = getParentReference().resolve();
+ if (parent == null) return null;
+
+ JpsElementCollection<? extends S> collection = getCollection(parent);
+ if (collection == null) return null;
+
+ final List<? extends S> elements = collection.getElements();
+ for (S element : elements) {
+ if (element.getName().equals(myElementName)) {
+ T resolved = resolve(element);
+ if (resolved != null) {
+ return resolved;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ protected abstract JpsElementCollection<? extends S> getCollection(@NotNull JpsCompositeElement parent);
+
+ @Nullable
+ protected abstract T resolve(S element);
+
+ public JpsElementReference<? extends JpsCompositeElement> getParentReference() {
+ return myContainer.getChild(PARENT_REFERENCE_ROLE);
+ }
+
+ @Override
+ public JpsElementReference<T> asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java
new file mode 100644
index 000000000000..ec70fd94abc2
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsNamedElement;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+
+/**
+ * @author nik
+ */
+public abstract class JpsNamedElementReferenceImpl<T extends JpsNamedElement, Self extends JpsNamedElementReferenceImpl<T, Self>> extends JpsNamedElementReferenceBase<T, T, Self> {
+ protected final JpsElementCollectionRole<? extends T> myCollectionRole;
+
+ protected JpsNamedElementReferenceImpl(@NotNull JpsElementCollectionRole<? extends T> role, @NotNull String elementName,
+ @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
+ super(elementName, parentReference);
+ myCollectionRole = role;
+ }
+
+ protected JpsNamedElementReferenceImpl(JpsNamedElementReferenceImpl<T, Self> original) {
+ super(original);
+ myCollectionRole = original.myCollectionRole;
+ }
+
+ @Override
+ protected T resolve(T element) {
+ return element;
+ }
+
+ @Nullable
+ protected JpsElementCollection<? extends T> getCollection(@NotNull JpsCompositeElement parent) {
+ return parent.getContainer().getChild(myCollectionRole);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectElementReference.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectElementReference.java
new file mode 100644
index 000000000000..adb28ed3b1f1
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectElementReference.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementReferenceBase;
+
+/**
+ * @author nik
+ */
+public class JpsProjectElementReference extends JpsElementReferenceBase<JpsProjectElementReference, JpsProject> {
+ @Override
+ public JpsProject resolve() {
+ final JpsModel model = getModel();
+ return model != null ? model.getProject() : null;
+ }
+
+ @NotNull
+ @Override
+ public JpsProjectElementReference createCopy() {
+ return new JpsProjectElementReference();
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsProjectElementReference modified) {
+ }
+
+ @Override
+ public String toString() {
+ return "project ref";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectImpl.java
new file mode 100644
index 000000000000..e210fc5836cd
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsProjectImpl.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.impl.runConfiguration.JpsRunConfigurationImpl;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryCollection;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.impl.JpsLibraryCollectionImpl;
+import org.jetbrains.jps.model.library.impl.JpsLibraryRole;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.model.module.JpsSdkReferencesTable;
+import org.jetbrains.jps.model.module.JpsTypedModule;
+import org.jetbrains.jps.model.module.impl.JpsModuleImpl;
+import org.jetbrains.jps.model.module.impl.JpsModuleRole;
+import org.jetbrains.jps.model.module.impl.JpsSdkReferencesTableImpl;
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfiguration;
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfigurationType;
+import org.jetbrains.jps.model.runConfiguration.JpsTypedRunConfiguration;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsProjectImpl extends JpsRootElementBase<JpsProjectImpl> implements JpsProject {
+ private static final JpsElementCollectionRole<JpsElementReference<?>> EXTERNAL_REFERENCES_COLLECTION_ROLE =
+ JpsElementCollectionRole.create(JpsElementChildRoleBase.<JpsElementReference<?>>create("external reference"));
+ private static final JpsElementCollectionRole<JpsRunConfiguration> RUN_CONFIGURATIONS_ROLE = JpsElementCollectionRole.create(JpsElementChildRoleBase.<JpsRunConfiguration>create("run configuration"));
+ private final JpsLibraryCollection myLibraryCollection;
+ private String myName = "";
+
+ public JpsProjectImpl(@NotNull JpsModel model, JpsEventDispatcher eventDispatcher) {
+ super(model, eventDispatcher);
+ myContainer.setChild(JpsModuleRole.MODULE_COLLECTION_ROLE);
+ myContainer.setChild(EXTERNAL_REFERENCES_COLLECTION_ROLE);
+ myContainer.setChild(JpsSdkReferencesTableImpl.ROLE);
+ myContainer.setChild(RUN_CONFIGURATIONS_ROLE);
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.setChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ }
+
+ public JpsProjectImpl(JpsProjectImpl original, JpsModel model, JpsEventDispatcher eventDispatcher) {
+ super(original, model, eventDispatcher);
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public void setName(@NotNull String name) {
+ if (!Comparing.equal(myName, name)) {
+ myName = name;
+ fireElementChanged();
+ }
+ }
+
+ public void addExternalReference(@NotNull JpsElementReference<?> reference) {
+ myContainer.getChild(EXTERNAL_REFERENCES_COLLECTION_ROLE).addChild(reference);
+ }
+
+ @NotNull
+ @Override
+ public
+ <P extends JpsElement, ModuleType extends JpsModuleType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsModule addModule(@NotNull final String name, @NotNull ModuleType moduleType) {
+ final JpsElementCollection<JpsModule> collection = myContainer.getChild(JpsModuleRole.MODULE_COLLECTION_ROLE);
+ return collection.addChild(new JpsModuleImpl<P>(moduleType, name, moduleType.createDefaultProperties()));
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull String name, @NotNull LibraryType libraryType) {
+ return myLibraryCollection.addLibrary(name, libraryType);
+ }
+
+ @NotNull
+ @Override
+ public List<JpsModule> getModules() {
+ return myContainer.getChild(JpsModuleRole.MODULE_COLLECTION_ROLE).getElements();
+ }
+
+ @Override
+ @NotNull
+ public <P extends JpsElement> Iterable<JpsTypedModule<P>> getModules(JpsModuleType<P> type) {
+ return myContainer.getChild(JpsModuleRole.MODULE_COLLECTION_ROLE).getElementsOfType(type);
+ }
+
+ @Override
+ public void addModule(@NotNull JpsModule module) {
+ myContainer.getChild(JpsModuleRole.MODULE_COLLECTION_ROLE).addChild(module);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryCollection getLibraryCollection() {
+ return myLibraryCollection;
+ }
+
+ @Override
+ @NotNull
+ public JpsSdkReferencesTable getSdkReferencesTable() {
+ return myContainer.getChild(JpsSdkReferencesTableImpl.ROLE);
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> Iterable<JpsTypedRunConfiguration<P>> getRunConfigurations(JpsRunConfigurationType<P> type) {
+ return getRunConfigurationsCollection().getElementsOfType(type);
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> JpsTypedRunConfiguration<P> addRunConfiguration(@NotNull String name,
+ @NotNull JpsRunConfigurationType<P> type,
+ @NotNull P properties) {
+ return getRunConfigurationsCollection().addChild(new JpsRunConfigurationImpl<P>(name, type, properties));
+ }
+
+ private JpsElementCollection<JpsRunConfiguration> getRunConfigurationsCollection() {
+ return myContainer.getChild(RUN_CONFIGURATIONS_ROLE);
+ }
+
+ @NotNull
+ @Override
+ public JpsElementReference<JpsProject> createReference() {
+ return new JpsProjectElementReference();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsRootElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsRootElementBase.java
new file mode 100644
index 000000000000..b3fd98644043
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsRootElementBase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+
+/**
+ * @author nik
+ */
+public abstract class JpsRootElementBase<E extends JpsRootElementBase<E>> extends JpsCompositeElementBase<E> {
+ private final JpsModel myModel;
+ private final JpsEventDispatcher myEventDispatcher;
+
+ protected JpsRootElementBase(@NotNull JpsModel model, JpsEventDispatcher eventDispatcher) {
+ super();
+ myModel = model;
+ myEventDispatcher = eventDispatcher;
+ }
+
+ protected JpsRootElementBase(JpsCompositeElementBase<E> original, JpsModel model, JpsEventDispatcher dispatcher) {
+ super(original);
+ myModel = model;
+ myEventDispatcher = dispatcher;
+ }
+
+ @Override
+ protected JpsEventDispatcher getEventDispatcher() {
+ return myEventDispatcher;
+ }
+
+ @NotNull
+ @Override
+ public JpsModel getModel() {
+ return myModel;
+ }
+
+ @NotNull
+ @Override
+ public E createCopy() {
+ throw new UnsupportedOperationException("'createCopy' not implemented in " + getClass().getName());
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsSimpleElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsSimpleElementImpl.java
new file mode 100644
index 000000000000..4f002b03e52b
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsSimpleElementImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+/**
+ * @author nik
+ */
+public class JpsSimpleElementImpl<D> extends JpsElementBase<JpsSimpleElementImpl<D>> implements JpsSimpleElement<D> {
+ private D myData;
+
+ public JpsSimpleElementImpl(D data) {
+ myData = data;
+ }
+
+ private JpsSimpleElementImpl(JpsSimpleElementImpl<D> original) {
+ myData = original.myData;
+ }
+
+ @NotNull
+ @Override
+ public D getData() {
+ return myData;
+ }
+
+ @Override
+ public void setData(@NotNull D data) {
+ if (!myData.equals(data)) {
+ myData = data;
+ fireElementChanged();
+ }
+ }
+
+ @NotNull
+ @Override
+ public JpsSimpleElementImpl<D> createCopy() {
+ return new JpsSimpleElementImpl<D>(this);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsSimpleElementImpl<D> modified) {
+ setData(modified.getData());
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListImpl.java
new file mode 100644
index 000000000000..c6be751f6d69
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsUrlListImpl extends JpsElementBase<JpsUrlListImpl> implements JpsUrlList {
+ private List<String> myUrls = new ArrayList<String>();
+
+ public JpsUrlListImpl() {
+ }
+
+ public JpsUrlListImpl(JpsUrlListImpl list) {
+ myUrls.addAll(list.myUrls);
+ }
+
+ @NotNull
+ @Override
+ public JpsUrlListImpl createCopy() {
+ return new JpsUrlListImpl(this);
+ }
+
+ @NotNull
+ @Override
+ public List<String> getUrls() {
+ return myUrls;
+ }
+
+ @Override
+ public void addUrl(@NotNull String url) {
+ myUrls.add(url);
+ fireElementChanged();
+ }
+
+ @Override
+ public void removeUrl(@NotNull String url) {
+ myUrls.remove(url);
+ fireElementChanged();
+ }
+
+ public void applyChanges(@NotNull JpsUrlListImpl modified) {
+ if (!myUrls.equals(modified.myUrls)) {
+ myUrls.clear();
+ myUrls.addAll(modified.myUrls);
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListRole.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListRole.java
new file mode 100644
index 000000000000..8385b5dc5efb
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsUrlListRole.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.JpsUrlList;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+/**
+ * @author nik
+ */
+public class JpsUrlListRole extends JpsElementChildRoleBase<JpsUrlList> implements JpsElementCreator<JpsUrlList> {
+ public JpsUrlListRole(String debugName) {
+ super(debugName);
+ }
+
+ @NotNull
+ @Override
+ public JpsUrlList create() {
+ return new JpsUrlListImpl();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/runConfiguration/JpsRunConfigurationImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/runConfiguration/JpsRunConfigurationImpl.java
new file mode 100644
index 000000000000..1bb496b30d90
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/runConfiguration/JpsRunConfigurationImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.impl.runConfiguration;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase;
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfigurationType;
+import org.jetbrains.jps.model.runConfiguration.JpsTypedRunConfiguration;
+
+/**
+ * @author nik
+ */
+public class JpsRunConfigurationImpl<P extends JpsElement> extends JpsNamedCompositeElementBase<JpsRunConfigurationImpl<P>> implements
+ JpsTypedRunConfiguration<P> {
+ private final JpsRunConfigurationType<P> myType;
+
+ public JpsRunConfigurationImpl(@NotNull String name, JpsRunConfigurationType<P> type, P properties) {
+ super(name);
+ myType = type;
+ myContainer.setChild(myType.getPropertiesRole(), properties);
+ }
+
+ private JpsRunConfigurationImpl(JpsRunConfigurationImpl<P> original) {
+ super(original);
+ myType = original.myType;
+ }
+
+ @NotNull
+ @Override
+ public JpsRunConfigurationImpl<P> createCopy() {
+ return new JpsRunConfigurationImpl<P>(this);
+ }
+
+ @NotNull
+ @Override
+ public P getProperties() {
+ return myContainer.getChild(myType.getPropertiesRole());
+ }
+
+ @Override
+ public JpsRunConfigurationType<P> getType() {
+ return myType;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/ExplodedDirectoryModuleExtensionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/ExplodedDirectoryModuleExtensionImpl.java
new file mode 100644
index 000000000000..a025df147322
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/ExplodedDirectoryModuleExtensionImpl.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.ExplodedDirectoryModuleExtension;
+
+/**
+ * @author nik
+ */
+public class ExplodedDirectoryModuleExtensionImpl extends JpsElementBase<ExplodedDirectoryModuleExtensionImpl> implements
+ ExplodedDirectoryModuleExtension {
+ private String myExplodedUrl;
+ private boolean myExcludeExploded;
+
+ public ExplodedDirectoryModuleExtensionImpl() {
+ }
+
+ public ExplodedDirectoryModuleExtensionImpl(ExplodedDirectoryModuleExtensionImpl original) {
+ myExcludeExploded = original.myExcludeExploded;
+ myExplodedUrl = original.myExplodedUrl;
+ }
+
+ @Override
+ public String getExplodedUrl() {
+ return myExplodedUrl;
+ }
+
+ @Override
+ public void setExplodedUrl(String explodedUrl) {
+ if (!Comparing.equal(myExplodedUrl, explodedUrl)) {
+ myExplodedUrl = explodedUrl;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public boolean isExcludeExploded() {
+ return myExcludeExploded;
+ }
+
+ @Override
+ public void setExcludeExploded(boolean excludeExploded) {
+ if (myExcludeExploded != excludeExploded) {
+ myExcludeExploded = excludeExploded;
+ fireElementChanged();
+ }
+ }
+
+ @NotNull
+ @Override
+ public ExplodedDirectoryModuleExtensionImpl createCopy() {
+ return new ExplodedDirectoryModuleExtensionImpl(this);
+ }
+
+ @Override
+ public void applyChanges(@NotNull ExplodedDirectoryModuleExtensionImpl modified) {
+ setExcludeExploded(modified.myExcludeExploded);
+ setExplodedUrl(modified.myExplodedUrl);
+ }
+
+ public static class ExplodedDirectoryModuleExtensionRole extends JpsElementChildRoleBase<ExplodedDirectoryModuleExtension> implements JpsElementCreator<ExplodedDirectoryModuleExtension> {
+ public static final ExplodedDirectoryModuleExtensionRole INSTANCE = new ExplodedDirectoryModuleExtensionRole();
+
+ public ExplodedDirectoryModuleExtensionRole() {
+ super("exploded directory");
+ }
+
+ @NotNull
+ @Override
+ public ExplodedDirectoryModuleExtension create() {
+ return new ExplodedDirectoryModuleExtensionImpl();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaModuleExtensionRole.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaModuleExtensionRole.java
new file mode 100644
index 000000000000..0f2f20a5e96e
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaModuleExtensionRole.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
+
+/**
+ * @author nik
+ */
+public class JavaModuleExtensionRole extends JpsElementChildRoleBase<JpsJavaModuleExtension> implements JpsElementCreator<JpsJavaModuleExtension> {
+ public static final JavaModuleExtensionRole INSTANCE = new JavaModuleExtensionRole();
+
+ private JavaModuleExtensionRole() {
+ super("java module extension");
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaModuleExtensionImpl create() {
+ return new JpsJavaModuleExtensionImpl();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaProjectExtensionRole.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaProjectExtensionRole.java
new file mode 100644
index 000000000000..7b4390703627
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaProjectExtensionRole.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.JpsJavaProjectExtension;
+
+/**
+ * @author nik
+ */
+public class JavaProjectExtensionRole extends JpsElementChildRoleBase<JpsJavaProjectExtension> implements JpsElementCreator<JpsJavaProjectExtension> {
+ public static final JavaProjectExtensionRole INSTANCE = new JavaProjectExtensionRole();
+
+ public JavaProjectExtensionRole() {
+ super("java project extension");
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaProjectExtension create() {
+ return new JpsJavaProjectExtensionImpl();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java
new file mode 100644
index 000000000000..32a5a258f268
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JavaSdkUtil {
+ public static List<File> getJdkClassesRoots(File home, boolean isJre) {
+ FileFilter jarFileFilter = new FileFilter() {
+ @Override
+ @SuppressWarnings({"HardCodedStringLiteral"})
+ public boolean accept(File f) {
+ return !f.isDirectory() && f.getName().endsWith(".jar");
+ }
+ };
+
+ File[] jarDirs;
+ if (SystemInfo.isMac && !home.getName().startsWith("mockJDK")) {
+ File openJdkRtJar = new File(home, "jre/lib/rt.jar");
+ if (openJdkRtJar.exists() && !openJdkRtJar.isDirectory()) {
+ File libDir = new File(home, "lib");
+ File classesDir = openJdkRtJar.getParentFile();
+ File libExtDir = new File(openJdkRtJar.getParentFile(), "ext");
+ File libEndorsedDir = new File(libDir, "endorsed");
+ jarDirs = new File[]{libEndorsedDir, libDir, classesDir, libExtDir};
+ }
+ else {
+ File libDir = new File(home, "lib");
+ File classesDir = new File(home, "../Classes");
+ File libExtDir = new File(libDir, "ext");
+ File libEndorsedDir = new File(libDir, "endorsed");
+ jarDirs = new File[]{libEndorsedDir, libDir, classesDir, libExtDir};
+ }
+ }
+ else {
+ File libDir = isJre ? new File(home, "lib") : new File(home, "jre/lib");
+ File libExtDir = new File(libDir, "ext");
+ File libEndorsedDir = new File(libDir, "endorsed");
+ jarDirs = new File[]{libEndorsedDir, libDir, libExtDir};
+ }
+
+ Set<String> pathFilter = ContainerUtil.newTroveSet(FileUtil.PATH_HASHING_STRATEGY);
+ List<File> rootFiles = ContainerUtil.newArrayList();
+ for (File jarDir : jarDirs) {
+ if (jarDir != null && jarDir.isDirectory()) {
+ File[] jarFiles = jarDir.listFiles(jarFileFilter);
+ for (File jarFile : jarFiles) {
+ String jarFileName = jarFile.getName();
+ if (jarFileName.equals("alt-rt.jar") || jarFileName.equals("alt-string.jar")) {
+ continue; // filter out alternative implementations
+ }
+ String canonicalPath = getCanonicalPath(jarFile);
+ if (canonicalPath == null || !pathFilter.add(canonicalPath)) {
+ continue; // filter out duplicate (symbolically linked) .jar files commonly found in OS X JDK distributions
+ }
+ rootFiles.add(jarFile);
+ }
+ }
+ }
+
+ File classesZip = new File(home, "lib/classes.zip");
+ if (classesZip.isFile()) {
+ rootFiles.add(classesZip);
+ }
+
+ File classesDir = new File(home, "classes");
+ if (rootFiles.isEmpty() && classesDir.isDirectory()) {
+ rootFiles.add(classesDir);
+ }
+
+ return rootFiles;
+ }
+
+ @Nullable
+ private static String getCanonicalPath(File file) {
+ try {
+ return file.getCanonicalPath();
+ }
+ catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java
new file mode 100644
index 000000000000..fecb068d4efd
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JdkVersionDetector;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.*;
+import java.util.concurrent.Future;
+
+/**
+ * @author nik
+ */
+public class JdkVersionDetectorImpl extends JdkVersionDetector {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.SdkVersionUtil");
+ private static final ActionRunner ACTION_RUNNER = new ActionRunner() {
+ @Override
+ public Future<?> run(Runnable runnable) {
+ return SharedThreadPool.getInstance().executeOnPooledThread(runnable);
+ }
+ };
+
+ @Override
+ @Nullable
+ public String detectJdkVersion(String homePath) {
+ return detectJdkVersion(homePath, ACTION_RUNNER);
+ }
+
+ @Nullable
+ public String detectJdkVersion(String homePath, final ActionRunner actionRunner) {
+ String[] command = {homePath + File.separator + "bin" + File.separator + "java", "-version"};
+ return readVersionFromProcessOutput(homePath, command, "version", actionRunner);
+ }
+
+ public String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
+ ActionRunner actionRunner) {
+ if (homePath == null || !new File(homePath).exists()) {
+ return null;
+ }
+ final String[] versionString = new String[1];
+ try {
+ //noinspection HardCodedStringLiteral
+ Process process = Runtime.getRuntime().exec(command);
+ VersionParsingThread parsingThread = new VersionParsingThread(process.getErrorStream(), versionString, versionLineMarker);
+ final Future<?> parsingThreadFuture = actionRunner.run(parsingThread);
+ ReadStreamThread readThread = new ReadStreamThread(process.getInputStream());
+ actionRunner.run(readThread);
+
+ try {
+ try {
+ process.waitFor();
+ }
+ catch (InterruptedException e) {
+ LOG.info(e);
+ process.destroy();
+ }
+ }
+ finally {
+ try {
+ parsingThreadFuture.get();
+ }
+ catch (Exception e) {
+ LOG.info(e);
+ }
+ }
+ }
+ catch (IOException ex) {
+ LOG.info(ex);
+ }
+ return versionString[0];
+ }
+
+ public static class ReadStreamThread implements Runnable {
+ private final InputStream myStream;
+
+ protected ReadStreamThread(InputStream stream) {
+ myStream = stream;
+ }
+
+ public void run() {
+ try {
+ while (true) {
+ int b = myStream.read();
+ if (b == -1) break;
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ }
+ }
+
+ public static class VersionParsingThread implements Runnable {
+ private Reader myReader;
+ private final InputStream myStream;
+ private boolean mySkipLF = false;
+ private final String[] myVersionString;
+ private final String myVersionLineMarker;
+
+ protected VersionParsingThread(InputStream input, String[] versionString, String versionLineMarker) {
+ myStream = input;
+ myVersionString = versionString;
+ myVersionLineMarker = versionLineMarker;
+ }
+
+ public void run() {
+ try {
+ myReader = new InputStreamReader(myStream);
+ while (true) {
+ String line = readLine();
+ if (line == null) return;
+ if (line.contains(myVersionLineMarker)) {
+ myVersionString[0] = line;
+ }
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ finally {
+ if (myReader != null){
+ try {
+ myReader.close();
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ }
+ }
+ }
+
+ private String readLine() throws IOException {
+ boolean first = true;
+ StringBuilder buffer = new StringBuilder();
+ while (true) {
+ int c = myReader.read();
+ if (c == -1) break;
+ first = false;
+ if (c == '\n') {
+ if (mySkipLF) {
+ mySkipLF = false;
+ continue;
+ }
+ break;
+ }
+ else if (c == '\r') {
+ mySkipLF = true;
+ break;
+ }
+ else {
+ mySkipLF = false;
+ buffer.append((char)c);
+ }
+ }
+ if (first) return null;
+ String s = buffer.toString();
+ //if (Diagnostic.TRACE_ENABLED){
+ // Diagnostic.trace(s);
+ //}
+ return s;
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumerationHandler.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumerationHandler.java
new file mode 100644
index 000000000000..fe5d18cb7205
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumerationHandler.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsJavaDependenciesEnumerationHandler {
+ public static List<JpsJavaDependenciesEnumerationHandler> createHandlers(Collection<JpsModule> rootModules) {
+ List<JpsJavaDependenciesEnumerationHandler> handlers = null;
+ for (Factory factory : JpsServiceManager.getInstance().getExtensions(Factory.class)) {
+ JpsJavaDependenciesEnumerationHandler handler = factory.createHandler(rootModules);
+ if (handler != null) {
+ if (handlers == null) {
+ handlers = new SmartList<JpsJavaDependenciesEnumerationHandler>();
+ }
+ handlers.add(handler);
+ }
+ }
+ return handlers;
+ }
+
+ public static boolean shouldProcessDependenciesRecursively(final List<JpsJavaDependenciesEnumerationHandler> handlers) {
+ if (handlers != null) {
+ for (JpsJavaDependenciesEnumerationHandler handler : handlers) {
+ if (!handler.shouldProcessDependenciesRecursively()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public static abstract class Factory {
+
+ @Nullable
+ public abstract JpsJavaDependenciesEnumerationHandler createHandler(@NotNull Collection<JpsModule> modules);
+ }
+ public boolean shouldAddRuntimeDependenciesToTestCompilationClasspath() {
+ return false;
+ }
+
+ public boolean isProductionOnTestsDependency(JpsDependencyElement element) {
+ return false;
+ }
+
+ public boolean shouldIncludeTestsFromDependentModulesToTestClasspath() {
+ return true;
+ }
+
+ public boolean shouldProcessDependenciesRecursively() {
+ return true;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java
new file mode 100644
index 000000000000..17edcceb6271
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsSdkDependency;
+import org.jetbrains.jps.model.module.impl.JpsDependenciesEnumeratorBase;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsJavaDependenciesEnumeratorImpl extends JpsDependenciesEnumeratorBase<JpsJavaDependenciesEnumeratorImpl> implements JpsJavaDependenciesEnumerator {
+ private boolean myProductionOnly;
+ private boolean myRuntimeOnly;
+ private boolean myCompileOnly;
+ private boolean myExportedOnly;
+ private boolean myRecursivelyExportedOnly;
+ private JpsJavaClasspathKind myClasspathKind;
+ private final List<JpsJavaDependenciesEnumerationHandler> myHandlers;
+
+ public JpsJavaDependenciesEnumeratorImpl(Collection<JpsModule> rootModules) {
+ super(rootModules);
+ List<JpsJavaDependenciesEnumerationHandler> handlers = JpsJavaDependenciesEnumerationHandler.createHandlers(rootModules);
+ myHandlers = handlers != null ? handlers : Collections.<JpsJavaDependenciesEnumerationHandler>emptyList();
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator productionOnly() {
+ myProductionOnly = true;
+ return this;
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator compileOnly() {
+ myCompileOnly = true;
+ return this;
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator runtimeOnly() {
+ myRuntimeOnly = true;
+ return this;
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator exportedOnly() {
+ if (myRecursively) {
+ myRecursivelyExportedOnly = true;
+ }
+ else {
+ myExportedOnly = true;
+ }
+ return this;
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind) {
+ myClasspathKind = classpathKind;
+ return this;
+ }
+
+ @Override
+ public JpsJavaDependenciesRootsEnumerator classes() {
+ return new JpsJavaDependenciesRootsEnumeratorImpl(this, JpsOrderRootType.COMPILED);
+ }
+
+ @Override
+ public JpsJavaDependenciesRootsEnumerator sources() {
+ return new JpsJavaDependenciesRootsEnumeratorImpl(this, JpsOrderRootType.SOURCES);
+ }
+
+ @Override
+ protected JpsJavaDependenciesEnumeratorImpl self() {
+ return this;
+ }
+
+ @Override
+ protected boolean shouldProcessDependenciesRecursively() {
+ return JpsJavaDependenciesEnumerationHandler.shouldProcessDependenciesRecursively(myHandlers);
+ }
+
+ @Override
+ protected boolean shouldProcess(JpsModule module, JpsDependencyElement element) {
+ boolean exported = !(element instanceof JpsSdkDependency);
+ JpsJavaDependencyExtension extension = JpsJavaExtensionService.getInstance().getDependencyExtension(element);
+ if (extension != null) {
+ exported = extension.isExported();
+ JpsJavaDependencyScope scope = extension.getScope();
+ boolean forTestCompile = scope.isIncludedIn(JpsJavaClasspathKind.TEST_COMPILE) || scope == JpsJavaDependencyScope.RUNTIME &&
+ shouldAddRuntimeDependenciesToTestCompilationClasspath();
+ if (myCompileOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE) && !forTestCompile
+ || myRuntimeOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME) && !scope.isIncludedIn(JpsJavaClasspathKind.TEST_RUNTIME)
+ || myClasspathKind != null && !scope.isIncludedIn(myClasspathKind) && !(myClasspathKind == JpsJavaClasspathKind.TEST_COMPILE && forTestCompile)) {
+ return false;
+ }
+ if (myProductionOnly) {
+ if (!scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE) && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME)
+ || myCompileOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE)
+ || myRuntimeOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME)) {
+ return false;
+ }
+ }
+ }
+ if (!exported) {
+ if (myExportedOnly) return false;
+ if (myRecursivelyExportedOnly && !isEnumerationRootModule(module)) return false;
+ }
+ return true;
+ }
+
+ public boolean isProductionOnly() {
+ return myProductionOnly || myClasspathKind == JpsJavaClasspathKind.PRODUCTION_RUNTIME || myClasspathKind == JpsJavaClasspathKind.PRODUCTION_COMPILE;
+ }
+
+ public boolean isProductionOnTests(JpsDependencyElement element) {
+ for (JpsJavaDependenciesEnumerationHandler handler : myHandlers) {
+ if (handler.isProductionOnTestsDependency(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean shouldIncludeTestsFromDependentModulesToTestClasspath() {
+ for (JpsJavaDependenciesEnumerationHandler handler : myHandlers) {
+ if (!handler.shouldIncludeTestsFromDependentModulesToTestClasspath()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean shouldAddRuntimeDependenciesToTestCompilationClasspath() {
+ for (JpsJavaDependenciesEnumerationHandler handler : myHandlers) {
+ if (handler.shouldAddRuntimeDependenciesToTestCompilationClasspath()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesRootsEnumeratorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesRootsEnumeratorImpl.java
new file mode 100644
index 000000000000..30b93e7856ad
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesRootsEnumeratorImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.util.Consumer;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaDependenciesRootsEnumerator;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.module.*;
+import org.jetbrains.jps.model.module.impl.JpsDependenciesRootsEnumeratorBase;
+
+/**
+ * @author nik
+ */
+public class JpsJavaDependenciesRootsEnumeratorImpl extends JpsDependenciesRootsEnumeratorBase<JpsJavaDependenciesEnumeratorImpl> implements JpsJavaDependenciesRootsEnumerator {
+ private boolean myWithoutSelfModuleOutput;
+
+ public JpsJavaDependenciesRootsEnumeratorImpl(JpsJavaDependenciesEnumeratorImpl dependenciesEnumerator, JpsOrderRootType rootType) {
+ super(dependenciesEnumerator, rootType);
+ }
+
+ @Override
+ public JpsJavaDependenciesRootsEnumerator withoutSelfModuleOutput() {
+ myWithoutSelfModuleOutput = true;
+ return this;
+ }
+
+ protected boolean processModuleRootUrls(JpsModule module, JpsDependencyElement dependencyElement, Consumer<String> urlConsumer) {
+ boolean includeProduction, includeTests;
+ if (dependencyElement instanceof JpsModuleDependency) {
+ boolean productionOnTests = myDependenciesEnumerator.isProductionOnTests(dependencyElement);
+ includeProduction = !productionOnTests;
+ includeTests = !myDependenciesEnumerator.isProductionOnly() && myDependenciesEnumerator.shouldIncludeTestsFromDependentModulesToTestClasspath()
+ || productionOnTests;
+ }
+ else {
+ includeProduction = true;
+ includeTests = !myDependenciesEnumerator.isProductionOnly();
+ }
+
+ if (myRootType == JpsOrderRootType.SOURCES) {
+ for (JpsModuleSourceRoot root : module.getSourceRoots()) {
+ JpsModuleSourceRootType<?> type = root.getRootType();
+ if (type.equals(JavaSourceRootType.SOURCE) && includeProduction || type.equals(JavaSourceRootType.TEST_SOURCE) && includeTests) {
+ urlConsumer.consume(root.getUrl());
+ }
+ }
+ }
+ else if (myRootType == JpsOrderRootType.COMPILED) {
+ JpsJavaExtensionService extensionService = JpsJavaExtensionService.getInstance();
+ if (myWithoutSelfModuleOutput && myDependenciesEnumerator.isEnumerationRootModule(module)) {
+ if (includeProduction && includeTests) {
+ String url = extensionService.getOutputUrl(module, false);
+ if (url != null) {
+ urlConsumer.consume(url);
+ }
+ }
+ }
+ else {
+ String outputUrl = extensionService.getOutputUrl(module, false);
+ if (includeTests) {
+ String testsOutputUrl = extensionService.getOutputUrl(module, true);
+ if (testsOutputUrl != null && !testsOutputUrl.equals(outputUrl)) {
+ urlConsumer.consume(testsOutputUrl);
+ }
+ }
+ if (includeProduction && outputUrl != null) {
+ urlConsumer.consume(outputUrl);
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionImpl.java
new file mode 100644
index 000000000000..de11854f0fb9
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionImpl.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.java.JpsJavaDependencyExtension;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+
+/**
+ * @author nik
+ */
+public class JpsJavaDependencyExtensionImpl extends JpsElementBase<JpsJavaDependencyExtensionImpl> implements JpsJavaDependencyExtension {
+ private boolean myExported;
+ private JpsJavaDependencyScope myScope;
+
+ public JpsJavaDependencyExtensionImpl(boolean exported,
+ JpsJavaDependencyScope scope) {
+ myExported = exported;
+ myScope = scope;
+ }
+
+ public JpsJavaDependencyExtensionImpl(JpsJavaDependencyExtensionImpl original) {
+ myExported = original.myExported;
+ myScope = original.myScope;
+ }
+
+ @Override
+ public boolean isExported() {
+ return myExported;
+ }
+
+ @Override
+ public void setExported(boolean exported) {
+ if (myExported != exported) {
+ myExported = exported;
+ fireElementChanged();
+ }
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaDependencyScope getScope() {
+ return myScope;
+ }
+
+ @Override
+ public void setScope(@NotNull JpsJavaDependencyScope scope) {
+ if (!scope.equals(myScope)) {
+ myScope = scope;
+ fireElementChanged();
+ }
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaDependencyExtensionImpl createCopy() {
+ return new JpsJavaDependencyExtensionImpl(this);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsJavaDependencyExtensionImpl modified) {
+ setExported(modified.myExported);
+ setScope(modified.myScope);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionRole.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionRole.java
new file mode 100644
index 000000000000..ebf4bc247029
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependencyExtensionRole.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.JpsJavaDependencyExtension;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+
+/**
+ * @author nik
+ */
+public class JpsJavaDependencyExtensionRole extends JpsElementChildRoleBase<JpsJavaDependencyExtension> implements JpsElementCreator<JpsJavaDependencyExtension> {
+ public static final JpsJavaDependencyExtensionRole INSTANCE = new JpsJavaDependencyExtensionRole();
+
+ private JpsJavaDependencyExtensionRole() {
+ super("java dependency extension");
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaDependencyExtensionImpl create() {
+ return new JpsJavaDependencyExtensionImpl(false, JpsJavaDependencyScope.COMPILE);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java
new file mode 100644
index 000000000000..a27142cb8b3e
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.impl.runConfiguration.JpsApplicationRunConfigurationPropertiesImpl;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationProperties;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationState;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsGlobal;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.impl.compiler.JpsJavaCompilerConfigurationImpl;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService {
+ @NotNull
+ @Override
+ public JpsJavaProjectExtension getOrCreateProjectExtension(@NotNull JpsProject project) {
+ return project.getContainer().getOrSetChild(JavaProjectExtensionRole.INSTANCE);
+ }
+
+ @Nullable
+ @Override
+ public JpsJavaProjectExtension getProjectExtension(@NotNull JpsProject project) {
+ return project.getContainer().getChild(JavaProjectExtensionRole.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaModuleExtension getOrCreateModuleExtension(@NotNull JpsModule module) {
+ return module.getContainer().getOrSetChild(JavaModuleExtensionRole.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaDependencyExtension getOrCreateDependencyExtension(@NotNull JpsDependencyElement dependency) {
+ return dependency.getContainer().getOrSetChild(JpsJavaDependencyExtensionRole.INSTANCE);
+ }
+
+ @Override
+ public JpsJavaDependencyExtension getDependencyExtension(@NotNull JpsDependencyElement dependency) {
+ return dependency.getContainer().getChild(JpsJavaDependencyExtensionRole.INSTANCE);
+ }
+
+ @Override
+ @Nullable
+ public JpsJavaModuleExtension getModuleExtension(@NotNull JpsModule module) {
+ return module.getContainer().getChild(JavaModuleExtensionRole.INSTANCE);
+ }
+
+ @Override
+ @NotNull
+ public ExplodedDirectoryModuleExtension getOrCreateExplodedDirectoryExtension(@NotNull JpsModule module) {
+ return module.getContainer().getOrSetChild(ExplodedDirectoryModuleExtensionImpl.ExplodedDirectoryModuleExtensionRole.INSTANCE);
+ }
+
+ @Override
+ @Nullable
+ public ExplodedDirectoryModuleExtension getExplodedDirectoryExtension(@NotNull JpsModule module) {
+ return module.getContainer().getChild(ExplodedDirectoryModuleExtensionImpl.ExplodedDirectoryModuleExtensionRole.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public List<JpsDependencyElement> getDependencies(JpsModule module, JpsJavaClasspathKind classpathKind, boolean exportedOnly) {
+ final List<JpsDependencyElement> result = new ArrayList<JpsDependencyElement>();
+ for (JpsDependencyElement dependencyElement : module.getDependenciesList().getDependencies()) {
+ final JpsJavaDependencyExtension extension = getDependencyExtension(dependencyElement);
+ if (extension == null || extension.getScope().isIncludedIn(classpathKind) && (!exportedOnly || extension.isExported())) {
+ result.add(dependencyElement);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public LanguageLevel getLanguageLevel(JpsModule module) {
+ final JpsJavaModuleExtension moduleExtension = getModuleExtension(module);
+ if (moduleExtension == null) return null;
+ final LanguageLevel languageLevel = moduleExtension.getLanguageLevel();
+ if (languageLevel != null) return languageLevel;
+ final JpsJavaProjectExtension projectExtension = getProjectExtension(module.getProject());
+ return projectExtension != null ? projectExtension.getLanguageLevel() : null;
+ }
+
+ @Override
+ public String getOutputUrl(JpsModule module, boolean forTests) {
+ final JpsJavaModuleExtension extension = getModuleExtension(module);
+ if (extension == null) return null;
+ if (extension.isInheritOutput()) {
+ JpsJavaProjectExtension projectExtension = getProjectExtension(module.getProject());
+ if (projectExtension == null) return null;
+ final String url = projectExtension.getOutputUrl();
+ if (url == null) return null;
+ return url + "/" + (forTests ? "test" : "production") + "/" + module.getName();
+ }
+ return forTests ? extension.getTestOutputUrl() : extension.getOutputUrl();
+ }
+
+ @Nullable
+ @Override
+ public File getOutputDirectory(JpsModule module, boolean forTests) {
+ String url = getOutputUrl(module, forTests);
+ return url != null ? JpsPathUtil.urlToFile(url) : null;
+ }
+
+ @Override
+ public JpsTypedLibrary<JpsSdk<JpsDummyElement>> addJavaSdk(@NotNull JpsGlobal global, @NotNull String name, @NotNull String homePath) {
+ String version = JdkVersionDetector.getInstance().detectJdkVersion(homePath);
+ JpsTypedLibrary<JpsSdk<JpsDummyElement>> sdk = global.addSdk(name, homePath, version, JpsJavaSdkType.INSTANCE);
+ File homeDir = new File(FileUtil.toSystemDependentName(homePath));
+ List<File> roots = JavaSdkUtil.getJdkClassesRoots(homeDir, false);
+ for (File root : roots) {
+ sdk.addRoot(root, JpsOrderRootType.COMPILED);
+ }
+ return sdk;
+ }
+
+ @Nullable
+ @Override
+ public JpsJavaCompilerConfiguration getCompilerConfiguration(@NotNull JpsProject project) {
+ return project.getContainer().getChild(JpsJavaCompilerConfigurationImpl.ROLE);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaCompilerConfiguration getOrCreateCompilerConfiguration(@NotNull JpsProject project) {
+ JpsJavaCompilerConfiguration configuration = getCompilerConfiguration(project);
+ if (configuration == null) {
+ configuration = project.getContainer().setChild(JpsJavaCompilerConfigurationImpl.ROLE, new JpsJavaCompilerConfigurationImpl());
+ }
+ return configuration;
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkReference<JpsDummyElement> createWrappedJavaSdkReference(@NotNull JpsJavaSdkTypeWrapper sdkType,
+ @NotNull JpsSdkReference<?> wrapperReference) {
+ return new JpsWrappedJavaSdkReferenceImpl(sdkType, wrapperReference);
+ }
+
+ @NotNull
+ @Override
+ public JpsApplicationRunConfigurationProperties createRunConfigurationProperties(JpsApplicationRunConfigurationState state) {
+ return new JpsApplicationRunConfigurationPropertiesImpl(state);
+ }
+
+ @Override
+ @NotNull
+ public JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference) {
+ return new JpsProductionModuleOutputPackagingElementImpl(moduleReference);
+ }
+
+ @Override
+ @NotNull
+ public JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference) {
+ return new JpsTestModuleOutputPackagingElementImpl(moduleReference);
+ }
+
+ @Override
+ public JpsJavaDependenciesEnumerator enumerateDependencies(Collection<JpsModule> modules) {
+ return new JpsJavaDependenciesEnumeratorImpl(modules);
+ }
+
+ @Override
+ protected JpsJavaDependenciesEnumerator enumerateDependencies(JpsProject project) {
+ return new JpsJavaDependenciesEnumeratorImpl(project.getModules());
+ }
+
+ @Override
+ protected JpsJavaDependenciesEnumerator enumerateDependencies(JpsModule module) {
+ return new JpsJavaDependenciesEnumeratorImpl(Collections.singletonList(module));
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaModuleExtensionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaModuleExtensionImpl.java
new file mode 100644
index 000000000000..9852e91e60b2
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaModuleExtensionImpl.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsUrlList;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.impl.JpsUrlListRole;
+import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
+import org.jetbrains.jps.model.java.LanguageLevel;
+
+/**
+ * @author nik
+ */
+public class JpsJavaModuleExtensionImpl extends JpsCompositeElementBase<JpsJavaModuleExtensionImpl> implements JpsJavaModuleExtension {
+ private static final JpsUrlListRole JAVADOC_ROOTS_ROLE = new JpsUrlListRole("javadoc roots");
+ private static final JpsUrlListRole ANNOTATIONS_ROOTS_ROLE = new JpsUrlListRole("annotation roots");
+ private String myOutputUrl;
+ private String myTestOutputUrl;
+ private boolean myInheritOutput;
+ private boolean myExcludeOutput;
+ private LanguageLevel myLanguageLevel;
+
+ public JpsJavaModuleExtensionImpl() {
+ myContainer.setChild(JAVADOC_ROOTS_ROLE);
+ myContainer.setChild(ANNOTATIONS_ROOTS_ROLE);
+ }
+
+ private JpsJavaModuleExtensionImpl(JpsJavaModuleExtensionImpl original) {
+ super(original);
+ myOutputUrl = original.myOutputUrl;
+ myTestOutputUrl = original.myTestOutputUrl;
+ myLanguageLevel = original.myLanguageLevel;
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaModuleExtensionImpl createCopy() {
+ return new JpsJavaModuleExtensionImpl(this);
+ }
+
+ @Override
+ public JpsUrlList getAnnotationRoots() {
+ return myContainer.getChild(ANNOTATIONS_ROOTS_ROLE);
+ }
+
+ @Override
+ public JpsUrlList getJavadocRoots() {
+ return myContainer.getChild(JAVADOC_ROOTS_ROLE);
+ }
+
+ @Override
+ public String getOutputUrl() {
+ return myOutputUrl;
+ }
+
+ @Override
+ public void setOutputUrl(String outputUrl) {
+ if (!Comparing.equal(myOutputUrl, outputUrl)) {
+ myOutputUrl = outputUrl;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public String getTestOutputUrl() {
+ return myTestOutputUrl;
+ }
+
+ @Override
+ public void setTestOutputUrl(String testOutputUrl) {
+ if (!Comparing.equal(myTestOutputUrl, testOutputUrl)) {
+ myTestOutputUrl = testOutputUrl;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public LanguageLevel getLanguageLevel() {
+ return myLanguageLevel;
+ }
+
+ @Override
+ public void setLanguageLevel(LanguageLevel languageLevel) {
+ if (!Comparing.equal(myLanguageLevel, languageLevel)) {
+ myLanguageLevel = languageLevel;
+ fireElementChanged();
+ }
+ }
+
+ public void applyChanges(@NotNull JpsJavaModuleExtensionImpl modified) {
+ setLanguageLevel(modified.myLanguageLevel);
+ setInheritOutput(modified.myInheritOutput);
+ setExcludeOutput(modified.myExcludeOutput);
+ setOutputUrl(modified.myOutputUrl);
+ setTestOutputUrl(modified.myTestOutputUrl);
+ }
+
+ @Override
+ public boolean isInheritOutput() {
+ return myInheritOutput;
+ }
+
+ @Override
+ public void setInheritOutput(boolean inheritOutput) {
+ if (myInheritOutput != inheritOutput) {
+ myInheritOutput = inheritOutput;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public boolean isExcludeOutput() {
+ return myExcludeOutput;
+ }
+
+ @Override
+ public void setExcludeOutput(boolean excludeOutput) {
+ if (myExcludeOutput != excludeOutput) {
+ myExcludeOutput = excludeOutput;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaProjectExtensionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaProjectExtensionImpl.java
new file mode 100644
index 000000000000..786b88f42549
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaProjectExtensionImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.java.JpsJavaProjectExtension;
+import org.jetbrains.jps.model.java.LanguageLevel;
+
+/**
+ * @author nik
+ */
+public class JpsJavaProjectExtensionImpl extends JpsElementBase<JpsJavaProjectExtensionImpl> implements JpsJavaProjectExtension {
+ private String myOutputUrl;
+ private LanguageLevel myLanguageLevel;
+
+ public JpsJavaProjectExtensionImpl() {
+ }
+
+ private JpsJavaProjectExtensionImpl(JpsJavaProjectExtensionImpl original) {
+ myOutputUrl = original.myOutputUrl;
+ myLanguageLevel = original.myLanguageLevel;
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaProjectExtensionImpl createCopy() {
+ return new JpsJavaProjectExtensionImpl(this);
+ }
+
+ public String getOutputUrl() {
+ return myOutputUrl;
+ }
+
+ public void setOutputUrl(String outputUrl) {
+ if (!Comparing.equal(myOutputUrl, outputUrl)) {
+ myOutputUrl = outputUrl;
+ fireElementChanged();
+ }
+ }
+
+ public LanguageLevel getLanguageLevel() {
+ return myLanguageLevel;
+ }
+
+ public void setLanguageLevel(LanguageLevel languageLevel) {
+ if (!Comparing.equal(myLanguageLevel, languageLevel)) {
+ myLanguageLevel = languageLevel;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsJavaProjectExtensionImpl modified) {
+ setLanguageLevel(modified.myLanguageLevel);
+ setOutputUrl(modified.myOutputUrl);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java
new file mode 100644
index 000000000000..7a2d120ae780
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.impl.elements.JpsModuleOutputPackagingElementBase;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public class JpsProductionModuleOutputPackagingElementImpl extends JpsModuleOutputPackagingElementBase<JpsProductionModuleOutputPackagingElementImpl>
+ implements JpsProductionModuleOutputPackagingElement {
+ public JpsProductionModuleOutputPackagingElementImpl(JpsModuleReference moduleReference) {
+ super(moduleReference);
+ }
+
+ private JpsProductionModuleOutputPackagingElementImpl(JpsProductionModuleOutputPackagingElementImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsProductionModuleOutputPackagingElementImpl createCopy() {
+ return new JpsProductionModuleOutputPackagingElementImpl(this);
+ }
+
+ @Override
+ protected String getOutputUrl(@NotNull JpsModule module) {
+ return JpsJavaExtensionService.getInstance().getOutputUrl(module, false);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java
new file mode 100644
index 000000000000..c215c821fbe2
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.artifact.impl.elements.JpsModuleOutputPackagingElementBase;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public class JpsTestModuleOutputPackagingElementImpl extends JpsModuleOutputPackagingElementBase<JpsTestModuleOutputPackagingElementImpl>
+ implements JpsTestModuleOutputPackagingElement {
+ public JpsTestModuleOutputPackagingElementImpl(JpsModuleReference moduleReference) {
+ super(moduleReference);
+ }
+
+ private JpsTestModuleOutputPackagingElementImpl(JpsTestModuleOutputPackagingElementImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsTestModuleOutputPackagingElementImpl createCopy() {
+ return new JpsTestModuleOutputPackagingElementImpl(this);
+ }
+
+ @Override
+ protected String getOutputUrl(@NotNull JpsModule module) {
+ return JpsJavaExtensionService.getInstance().getOutputUrl(module, true);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java
new file mode 100644
index 000000000000..fdc678f7b820
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+
+/**
+ * @author nik
+ */
+public class JpsWrappedJavaSdkReferenceImpl extends JpsCompositeElementBase<JpsWrappedJavaSdkReferenceImpl> implements JpsSdkReference<JpsDummyElement> {
+ private static final JpsElementChildRoleBase<JpsSdkReference<?>> WRAPPER_ROLE = JpsElementChildRoleBase.create("wrapper reference");
+ private final JpsJavaSdkTypeWrapper mySdkType;
+
+ public JpsWrappedJavaSdkReferenceImpl(JpsJavaSdkTypeWrapper sdkType, JpsSdkReference<?> wrapperReference) {
+ mySdkType = sdkType;
+ myContainer.setChild(WRAPPER_ROLE, wrapperReference);
+ }
+
+ private JpsWrappedJavaSdkReferenceImpl(JpsWrappedJavaSdkReferenceImpl original) {
+ super(original);
+ mySdkType = original.mySdkType;
+ }
+
+ @NotNull
+ @Override
+ public JpsWrappedJavaSdkReferenceImpl createCopy() {
+ return new JpsWrappedJavaSdkReferenceImpl(this);
+ }
+
+ @Override
+ public String getSdkName() {
+ JpsTypedLibrary<JpsSdk<JpsDummyElement>> sdk = resolve();
+ return sdk != null ? sdk.getName() : "<unknown>";
+ }
+
+ @Nullable
+ @Override
+ public JpsTypedLibrary<JpsSdk<JpsDummyElement>> resolve() {
+ JpsTypedLibrary<? extends JpsSdk<? extends JpsElement>> wrapper = myContainer.getChild(WRAPPER_ROLE).resolve();
+ if (wrapper == null) return null;
+ JpsModel model = getModel();
+ if (model == null) return null;
+ String sdkName = mySdkType.getJavaSdkName(wrapper.getProperties().getSdkProperties());
+ if (sdkName == null) return null;
+
+ JpsLibrary library = model.getGlobal().getLibraryCollection().findLibrary(sdkName);
+ return library != null ? library.asTyped(JpsJavaSdkType.INSTANCE) : null;
+ }
+
+ @Override
+ public JpsElementReference<JpsTypedLibrary<JpsSdk<JpsDummyElement>>> asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsCompilerExcludesImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsCompilerExcludesImpl.java
new file mode 100644
index 000000000000..315347621526
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsCompilerExcludesImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl.compiler;
+
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JpsCompilerExcludesImpl implements JpsCompilerExcludes {
+ private final Set<File> myFiles = new HashSet<File>();
+ private final Set<File> myDirectories = new HashSet<File>();
+ private final Set<File> myRecursivelyExcludedDirectories = new HashSet<File>();
+
+ @Override
+ public void addExcludedFile(String url) {
+ addExcludedFile(JpsPathUtil.urlToFile(url));
+ }
+
+ @Override
+ public void addExcludedDirectory(String url, boolean recursively) {
+ addExcludedDirectory(JpsPathUtil.urlToFile(url), recursively);
+ }
+
+ public void addExcludedFile(File file) {
+ myFiles.add(file);
+ }
+
+ public void addExcludedDirectory(File dir, boolean recursively) {
+ (recursively ? myRecursivelyExcludedDirectories : myDirectories).add(dir);
+ }
+
+ @Override
+ public boolean isExcluded(File file) {
+ if (myFiles.contains(file)) {
+ return true;
+ }
+
+ if (!myDirectories.isEmpty() || !myRecursivelyExcludedDirectories.isEmpty()) { // optimization
+ File parent = FileUtilRt.getParentFile(file);
+ if (myDirectories.contains(parent)) {
+ return true;
+ }
+
+ while (parent != null) {
+ if (myRecursivelyExcludedDirectories.contains(parent)) {
+ return true;
+ }
+ parent = FileUtilRt.getParentFile(parent);
+ }
+ }
+ return false;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java
new file mode 100644
index 000000000000..12d01689ea0a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl.compiler;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<JpsJavaCompilerConfigurationImpl> implements JpsJavaCompilerConfiguration {
+ public static final JpsElementChildRole<JpsJavaCompilerConfiguration> ROLE = JpsElementChildRoleBase.create("compiler configuration");
+ private boolean myAddNotNullAssertions = true;
+ private boolean myClearOutputDirectoryOnRebuild = true;
+ private JpsCompilerExcludes myCompilerExcludes = new JpsCompilerExcludesImpl();
+ private List<String> myResourcePatterns = new ArrayList<String>();
+ private List<ProcessorConfigProfile> myAnnotationProcessingProfiles = new ArrayList<ProcessorConfigProfile>();
+ private ProcessorConfigProfileImpl myDefaultAnnotationProcessingProfile = new ProcessorConfigProfileImpl("Default");
+ private String myProjectByteCodeTargetLevel;
+ private Map<String, String> myModulesByteCodeTargetLevels = new HashMap<String, String>();
+ private Map<String, JpsJavaCompilerOptions> myCompilerOptions = new HashMap<String, JpsJavaCompilerOptions>();
+ private String myJavaCompilerId = "Javac";
+ private Map<JpsModule, ProcessorConfigProfile> myAnnotationProcessingProfileMap;
+
+ public JpsJavaCompilerConfigurationImpl() {
+ }
+
+ private JpsJavaCompilerConfigurationImpl(JpsJavaCompilerConfigurationImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaCompilerConfigurationImpl createCopy() {
+ return new JpsJavaCompilerConfigurationImpl(this);
+ }
+
+ @Override
+ public boolean isAddNotNullAssertions() {
+ return myAddNotNullAssertions;
+ }
+
+ @Override
+ public boolean isClearOutputDirectoryOnRebuild() {
+ return myClearOutputDirectoryOnRebuild;
+ }
+
+ @Override
+ public void setAddNotNullAssertions(boolean addNotNullAssertions) {
+ myAddNotNullAssertions = addNotNullAssertions;
+ }
+
+ @Override
+ public void setClearOutputDirectoryOnRebuild(boolean clearOutputDirectoryOnRebuild) {
+ myClearOutputDirectoryOnRebuild = clearOutputDirectoryOnRebuild;
+ }
+
+ @NotNull
+ @Override
+ public JpsCompilerExcludes getCompilerExcludes() {
+ return myCompilerExcludes;
+ }
+
+ @NotNull
+ @Override
+ public ProcessorConfigProfile getDefaultAnnotationProcessingProfile() {
+ return myDefaultAnnotationProcessingProfile;
+ }
+
+ @NotNull
+ @Override
+ public Collection<ProcessorConfigProfile> getAnnotationProcessingProfiles() {
+ return myAnnotationProcessingProfiles;
+ }
+
+ @Override
+ public void addResourcePattern(String pattern) {
+ myResourcePatterns.add(pattern);
+ }
+
+ @Override
+ public List<String> getResourcePatterns() {
+ return myResourcePatterns;
+ }
+
+ @Override
+ @Nullable
+ public String getByteCodeTargetLevel(String moduleName) {
+ String level = myModulesByteCodeTargetLevels.get(moduleName);
+ if (level != null) {
+ return level.isEmpty() ? null : level;
+ }
+ return myProjectByteCodeTargetLevel;
+ }
+
+ @Override
+ public void setModuleByteCodeTargetLevel(String moduleName, String level) {
+ myModulesByteCodeTargetLevels.put(moduleName, level);
+ }
+
+ @NotNull
+ @Override
+ public String getJavaCompilerId() {
+ return myJavaCompilerId;
+ }
+
+ @Override
+ public void setJavaCompilerId(@NotNull String compiler) {
+ myJavaCompilerId = compiler;
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaCompilerOptions getCompilerOptions(@NotNull String compilerId) {
+ JpsJavaCompilerOptions options = myCompilerOptions.get(compilerId);
+ if (options == null) {
+ options = new JpsJavaCompilerOptions();
+ myCompilerOptions.put(compilerId, options);
+ }
+ return options;
+ }
+
+ @Override
+ public void setCompilerOptions(@NotNull String compilerId, @NotNull JpsJavaCompilerOptions options) {
+ myCompilerOptions.put(compilerId, options);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaCompilerOptions getCurrentCompilerOptions() {
+ return getCompilerOptions(getJavaCompilerId());
+ }
+
+ @Override
+ public void setProjectByteCodeTargetLevel(String level) {
+ myProjectByteCodeTargetLevel = level;
+ }
+
+ @Override
+ public ProcessorConfigProfile addAnnotationProcessingProfile() {
+ ProcessorConfigProfileImpl profile = new ProcessorConfigProfileImpl("");
+ myAnnotationProcessingProfiles.add(profile);
+ return profile;
+ }
+
+ @Override
+ @NotNull
+ public ProcessorConfigProfile getAnnotationProcessingProfile(JpsModule module) {
+ Map<JpsModule, ProcessorConfigProfile> map = myAnnotationProcessingProfileMap;
+ if (map == null) {
+ map = new HashMap<JpsModule, ProcessorConfigProfile>();
+ final Map<String, JpsModule> namesMap = new HashMap<String, JpsModule>();
+ for (JpsModule m : module.getProject().getModules()) {
+ namesMap.put(m.getName(), m);
+ }
+ if (!namesMap.isEmpty()) {
+ for (ProcessorConfigProfile profile : getAnnotationProcessingProfiles()) {
+ for (String name : profile.getModuleNames()) {
+ final JpsModule mod = namesMap.get(name);
+ if (mod != null) {
+ map.put(mod, profile);
+ }
+ }
+ }
+ }
+ myAnnotationProcessingProfileMap = map;
+ }
+ final ProcessorConfigProfile profile = map.get(module);
+ return profile != null? profile : getDefaultAnnotationProcessingProfile();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java
new file mode 100644
index 000000000000..4c554459ccad
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl.compiler;
+
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 5/25/12
+ */
+public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile {
+
+ private String myName = "";
+ private boolean myEnabled = false;
+ private boolean myObtainProcessorsFromClasspath = true;
+ private String myProcessorPath = "";
+ private final Set<String> myProcessors = new THashSet<String>(1); // empty list means all discovered
+ private final Map<String, String> myProcessorOptions = new THashMap<String, String>(1); // key=value map of options
+ private String myGeneratedProductionDirectoryName = DEFAULT_PRODUCTION_DIR_NAME;
+ private String myGeneratedTestsDirectoryName = DEFAULT_TESTS_DIR_NAME;
+ private boolean myOutputRelativeToContentRoot = false;
+
+ private final Set<String> myModuleNames = new THashSet<String>(1);
+
+ public ProcessorConfigProfileImpl(String name) {
+ myName = name;
+ }
+
+ public ProcessorConfigProfileImpl(ProcessorConfigProfile profile) {
+ initFrom(profile);
+ }
+
+ @Override
+ public final void initFrom(ProcessorConfigProfile other) {
+ myName = other.getName();
+ myEnabled = other.isEnabled();
+ myObtainProcessorsFromClasspath = other.isObtainProcessorsFromClasspath();
+ myProcessorPath = other.getProcessorPath();
+ myProcessors.clear();
+ myProcessors.addAll(other.getProcessors());
+ myProcessorOptions.clear();
+ myProcessorOptions.putAll(other.getProcessorOptions());
+ myGeneratedProductionDirectoryName = other.getGeneratedSourcesDirectoryName(false);
+ myGeneratedTestsDirectoryName = other.getGeneratedSourcesDirectoryName(true);
+ myOutputRelativeToContentRoot = other.isOutputRelativeToContentRoot();
+ myModuleNames.clear();
+ myModuleNames.addAll(other.getModuleNames());
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public void setName(String name) {
+ myName = name;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return myEnabled;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ myEnabled = enabled;
+ }
+
+ @Override
+ @NotNull
+ public String getProcessorPath() {
+ return myProcessorPath;
+ }
+
+ @Override
+ public void setProcessorPath(@Nullable String processorPath) {
+ myProcessorPath = processorPath != null? processorPath : "";
+ }
+
+ @Override
+ public boolean isObtainProcessorsFromClasspath() {
+ return myObtainProcessorsFromClasspath;
+ }
+
+ @Override
+ public void setObtainProcessorsFromClasspath(boolean value) {
+ myObtainProcessorsFromClasspath = value;
+ }
+
+ @Override
+ @NotNull
+ public String getGeneratedSourcesDirectoryName(boolean forTests) {
+ return forTests? myGeneratedTestsDirectoryName : myGeneratedProductionDirectoryName;
+ }
+
+ @Override
+ public void setGeneratedSourcesDirectoryName(@Nullable String name, boolean forTests) {
+ if (forTests) {
+ myGeneratedTestsDirectoryName = name != null? name.trim() : DEFAULT_TESTS_DIR_NAME;
+ }
+ else {
+ myGeneratedProductionDirectoryName = name != null? name.trim() : DEFAULT_PRODUCTION_DIR_NAME;
+ }
+ }
+
+ @Override
+ public boolean isOutputRelativeToContentRoot() {
+ return myOutputRelativeToContentRoot;
+ }
+
+ @Override
+ public void setOutputRelativeToContentRoot(boolean relativeToContent) {
+ myOutputRelativeToContentRoot = relativeToContent;
+ }
+
+ @Override
+ @NotNull
+ public Set<String> getModuleNames() {
+ return myModuleNames;
+ }
+
+ @Override
+ public boolean addModuleName(String name) {
+ return myModuleNames.add(name);
+ }
+
+ @Override
+ public boolean addModuleNames(Collection<String> names) {
+ return myModuleNames.addAll(names);
+ }
+
+ @Override
+ public boolean removeModuleName(String name) {
+ return myModuleNames.remove(name);
+ }
+
+ @Override
+ public boolean removeModuleNames(Collection<String> names) {
+ return myModuleNames.removeAll(names);
+ }
+
+ @Override
+ public void clearModuleNames() {
+ myModuleNames.clear();
+ }
+
+ @Override
+ public void clearProcessors() {
+ myProcessors.clear();
+ }
+
+ @Override
+ public boolean addProcessor(String processor) {
+ return myProcessors.add(processor);
+ }
+
+ @Override
+ public boolean removeProcessor(String processor) {
+ return myProcessors.remove(processor);
+ }
+
+ @Override
+ @NotNull
+ public Set<String> getProcessors() {
+ return Collections.unmodifiableSet(myProcessors);
+ }
+
+ @Override
+ @NotNull
+ public Map<String, String> getProcessorOptions() {
+ return Collections.unmodifiableMap(myProcessorOptions);
+ }
+
+ @Override
+ public String setOption(String key, String value) {
+ return myProcessorOptions.put(key, value);
+ }
+
+ @Override
+ @Nullable
+ public String getOption(String key) {
+ return myProcessorOptions.get(key);
+ }
+
+ @Override
+ public void clearProcessorOptions() {
+ myProcessorOptions.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ProcessorConfigProfileImpl profile = (ProcessorConfigProfileImpl)o;
+
+ if (myEnabled != profile.myEnabled) return false;
+ if (myObtainProcessorsFromClasspath != profile.myObtainProcessorsFromClasspath) return false;
+ if (myGeneratedProductionDirectoryName != null
+ ? !myGeneratedProductionDirectoryName.equals(profile.myGeneratedProductionDirectoryName)
+ : profile.myGeneratedProductionDirectoryName != null) {
+ return false;
+ }
+ if (myGeneratedTestsDirectoryName != null
+ ? !myGeneratedTestsDirectoryName.equals(profile.myGeneratedTestsDirectoryName)
+ : profile.myGeneratedTestsDirectoryName != null) {
+ return false;
+ }
+ if (myOutputRelativeToContentRoot != profile.myOutputRelativeToContentRoot)return false;
+ if (!myModuleNames.equals(profile.myModuleNames)) return false;
+ if (!myProcessorOptions.equals(profile.myProcessorOptions)) return false;
+ if (myProcessorPath != null ? !myProcessorPath.equals(profile.myProcessorPath) : profile.myProcessorPath != null) return false;
+ if (!myProcessors.equals(profile.myProcessors)) return false;
+ if (!myName.equals(profile.myName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName.hashCode();
+ result = 31 * result + (myEnabled ? 1 : 0);
+ result = 31 * result + (myObtainProcessorsFromClasspath ? 1 : 0);
+ result = 31 * result + (myProcessorPath != null ? myProcessorPath.hashCode() : 0);
+ result = 31 * result + myProcessors.hashCode();
+ result = 31 * result + myProcessorOptions.hashCode();
+ result = 31 * result + (myGeneratedProductionDirectoryName != null ? myGeneratedProductionDirectoryName.hashCode() : 0);
+ result = 31 * result + (myGeneratedTestsDirectoryName != null ? myGeneratedTestsDirectoryName.hashCode() : 0);
+ result = 31 * result + (myOutputRelativeToContentRoot ? 1 : 0);
+ result = 31 * result + myModuleNames.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return myName;
+ }
+}
+
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/runConfiguration/JpsApplicationRunConfigurationPropertiesImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/runConfiguration/JpsApplicationRunConfigurationPropertiesImpl.java
new file mode 100644
index 000000000000..5db63c8753b0
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/runConfiguration/JpsApplicationRunConfigurationPropertiesImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.java.impl.runConfiguration;
+
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationProperties;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationState;
+
+/**
+ * @author nik
+ */
+public class JpsApplicationRunConfigurationPropertiesImpl extends JpsElementBase<JpsApplicationRunConfigurationPropertiesImpl> implements JpsApplicationRunConfigurationProperties {
+ private JpsApplicationRunConfigurationState myState;
+
+ public JpsApplicationRunConfigurationPropertiesImpl(JpsApplicationRunConfigurationState state) {
+ myState = state;
+ }
+
+ @NotNull
+ @Override
+ public JpsApplicationRunConfigurationPropertiesImpl createCopy() {
+ return new JpsApplicationRunConfigurationPropertiesImpl(XmlSerializerUtil.createCopy(myState));
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsApplicationRunConfigurationPropertiesImpl modified) {
+ XmlSerializerUtil.copyBean(modified.myState, myState);
+ }
+
+ @Override
+ public String getMainClass() {
+ return myState.MAIN_CLASS_NAME;
+ }
+
+ @Override
+ public void setMainClass(String value) {
+ myState.MAIN_CLASS_NAME = value;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryCollectionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryCollectionImpl.java
new file mode 100644
index 000000000000..26b4b7141653
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryCollectionImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryCollection;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryCollectionImpl implements JpsLibraryCollection {
+ private final JpsElementCollection<JpsLibrary> myCollection;
+
+ public JpsLibraryCollectionImpl(JpsElementCollection<JpsLibrary> collection) {
+ myCollection = collection;
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement, LibraryType extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addLibrary(@NotNull String name, @NotNull LibraryType type) {
+ return addLibrary(name, type, type.createDefaultProperties());
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> JpsTypedLibrary<P> addLibrary(@NotNull String name, @NotNull JpsLibraryType<P> type,
+ @NotNull P properties) {
+ return myCollection.addChild(new JpsLibraryImpl<P>(name, type, properties));
+ }
+
+ @NotNull
+ @Override
+ public List<JpsLibrary> getLibraries() {
+ return myCollection.getElements();
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> Iterable<JpsTypedLibrary<P>> getLibraries(@NotNull JpsLibraryType<P> type) {
+ return myCollection.getElementsOfType(type);
+ }
+
+ @Override
+ public void addLibrary(@NotNull JpsLibrary library) {
+ myCollection.addChild(library);
+ }
+
+ @Override
+ public JpsLibrary findLibrary(@NotNull String name) {
+ for (JpsLibrary library : getLibraries()) {
+ if (name.equals(library.getName())) {
+ return library;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ @Nullable
+ public <E extends JpsElement> JpsTypedLibrary<E> findLibrary(@NotNull String name, @NotNull JpsLibraryType<E> type) {
+ for (JpsTypedLibrary<E> library : getLibraries(type)) {
+ if (name.equals(library.getName())) {
+ return library;
+ }
+ }
+ return null;
+ }
+
+
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java
new file mode 100644
index 000000000000..2e581d27f15b
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase;
+import org.jetbrains.jps.model.impl.JpsElementCollectionImpl;
+import org.jetbrains.jps.model.library.*;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryImpl<P extends JpsElement> extends JpsNamedCompositeElementBase<JpsLibraryImpl<P>> implements JpsTypedLibrary<P> {
+ private final JpsLibraryType<P> myLibraryType;
+
+ public JpsLibraryImpl(@NotNull String name, @NotNull JpsLibraryType<P> type, @NotNull P properties) {
+ super(name);
+ myLibraryType = type;
+ myContainer.setChild(myLibraryType.getPropertiesRole(), properties);
+ }
+
+ private JpsLibraryImpl(@NotNull JpsLibraryImpl<P> original) {
+ super(original);
+ myLibraryType = original.myLibraryType;
+ }
+
+ @Override
+ @NotNull
+ public JpsLibraryType<P> getType() {
+ return myLibraryType;
+ }
+
+ @Nullable
+ @Override
+ public <P extends JpsElement> JpsTypedLibrary<P> asTyped(@NotNull JpsLibraryType<P> type) {
+ //noinspection unchecked
+ return myLibraryType.equals(type) ? (JpsTypedLibrary<P>)this : null;
+ }
+
+ @NotNull
+ @Override
+ public P getProperties() {
+ return myContainer.getChild(myLibraryType.getPropertiesRole());
+ }
+
+ @NotNull
+ @Override
+ public List<JpsLibraryRoot> getRoots(@NotNull JpsOrderRootType rootType) {
+ final JpsElementCollection<JpsLibraryRoot> rootsCollection = myContainer.getChild(getRole(rootType));
+ return rootsCollection != null ? rootsCollection.getElements() : Collections.<JpsLibraryRoot>emptyList();
+ }
+
+ @Override
+ public void addRoot(@NotNull String url, @NotNull JpsOrderRootType rootType) {
+ addRoot(url, rootType, JpsLibraryRoot.InclusionOptions.ROOT_ITSELF);
+ }
+
+ @Override
+ public void addRoot(@NotNull File file, @NotNull JpsOrderRootType rootType) {
+ addRoot(JpsPathUtil.getLibraryRootUrl(file), rootType);
+ }
+
+ @Override
+ public void addRoot(@NotNull final String url, @NotNull final JpsOrderRootType rootType,
+ @NotNull JpsLibraryRoot.InclusionOptions options) {
+ myContainer.getOrSetChild(getRole(rootType)).addChild(new JpsLibraryRootImpl(url, rootType, options));
+ }
+
+ @Override
+ public void removeUrl(@NotNull final String url, @NotNull final JpsOrderRootType rootType) {
+ final JpsElementCollection<JpsLibraryRoot> rootsCollection = myContainer.getChild(getRole(rootType));
+ if (rootsCollection != null) {
+ for (JpsLibraryRoot root : rootsCollection.getElements()) {
+ if (root.getUrl().equals(url) && root.getRootType().equals(rootType)) {
+ rootsCollection.removeChild(root);
+ break;
+ }
+ }
+ }
+ }
+
+ private static JpsElementCollectionRole<JpsLibraryRoot> getRole(JpsOrderRootType type) {
+ return JpsElementCollectionRole.create(new JpsLibraryRootRole(type));
+ }
+
+ @Override
+ public void delete() {
+ getParent().removeChild(this);
+ }
+
+ public JpsElementCollectionImpl<JpsLibrary> getParent() {
+ //noinspection unchecked
+ return (JpsElementCollectionImpl<JpsLibrary>)myParent;
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryImpl<P> createCopy() {
+ return new JpsLibraryImpl<P>(this);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryReference createReference() {
+ return new JpsLibraryReferenceImpl(getName(), createParentReference());
+ }
+
+ private JpsElementReference<JpsCompositeElement> createParentReference() {
+ //noinspection unchecked
+ return ((JpsReferenceableElement<JpsCompositeElement>)getParent().getParent()).createReference();
+ }
+
+ @Override
+ public List<File> getFiles(final JpsOrderRootType rootType) {
+ List<String> urls = getRootUrls(rootType);
+ List<File> files = new ArrayList<File>(urls.size());
+ for (String url : urls) {
+ files.add(JpsPathUtil.urlToFile(url));
+ }
+ return files;
+ }
+
+ @Override
+ public List<String> getRootUrls(JpsOrderRootType rootType) {
+ List<String> urls = new ArrayList<String>();
+ for (JpsLibraryRoot root : getRoots(rootType)) {
+ switch (root.getInclusionOptions()) {
+ case ROOT_ITSELF:
+ urls.add(root.getUrl());
+ break;
+ case ARCHIVES_UNDER_ROOT:
+ collectArchives(JpsPathUtil.urlToFile(root.getUrl()), false, urls);
+ break;
+ case ARCHIVES_UNDER_ROOT_RECURSIVELY:
+ collectArchives(JpsPathUtil.urlToFile(root.getUrl()), true, urls);
+ break;
+ }
+ }
+ return urls;
+ }
+
+ private static final Set<String> AR_EXTENSIONS = ContainerUtil.newTroveSet(FileUtil.PATH_HASHING_STRATEGY, "jar", "zip", "swc", "ane");
+
+ private static void collectArchives(File file, boolean recursively, List<String> result) {
+ final File[] children = file.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ final String extension = FileUtilRt.getExtension(child.getName());
+ if (child.isDirectory()) {
+ if (recursively) {
+ collectArchives(child, recursively, result);
+ }
+ }
+ // todo [nik] get list of extensions mapped to Archive file type from IDE settings
+ else if (AR_EXTENSIONS.contains(extension)) {
+ result.add(JpsPathUtil.getLibraryRootUrl(child));
+ }
+ }
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryReferenceImpl.java
new file mode 100644
index 000000000000..73a236d5f9cd
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryReferenceImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.impl.JpsNamedElementReferenceImpl;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryReferenceImpl extends JpsNamedElementReferenceImpl<JpsLibrary, JpsLibraryReferenceImpl> implements JpsLibraryReference {
+ public JpsLibraryReferenceImpl(String elementName, JpsElementReference<? extends JpsCompositeElement> parentReference) {
+ super(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE, elementName, parentReference);
+ }
+
+ private JpsLibraryReferenceImpl(JpsLibraryReferenceImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public String getLibraryName() {
+ return myElementName;
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryReferenceImpl createCopy() {
+ return new JpsLibraryReferenceImpl(this);
+ }
+
+ @Override
+ public JpsLibraryReference asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "lib ref: '" + myElementName + "' in " + getParentReference();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java
new file mode 100644
index 000000000000..1c1492058878
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryListener;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryRole extends JpsElementChildRoleBase<JpsLibrary> {
+ public static final JpsLibraryRole INSTANCE = new JpsLibraryRole();
+ public static final JpsElementCollectionRole<JpsLibrary> LIBRARIES_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE);
+
+ private JpsLibraryRole() {
+ super("library");
+ }
+
+ @Override
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsLibrary element) {
+ dispatcher.getPublisher(JpsLibraryListener.class).libraryAdded(element);
+ }
+
+ @Override
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsLibrary element) {
+ dispatcher.getPublisher(JpsLibraryListener.class).libraryRemoved(element);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootImpl.java
new file mode 100644
index 000000000000..298c2c4ad5ad
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryRoot;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryRootImpl extends JpsElementBase<JpsLibraryRootImpl> implements JpsLibraryRoot {
+ private final String myUrl;
+ private final JpsOrderRootType myRootType;
+ private final InclusionOptions myOptions;
+
+ public JpsLibraryRootImpl(@NotNull String url, @NotNull JpsOrderRootType rootType, @NotNull InclusionOptions options) {
+ myUrl = url;
+ myRootType = rootType;
+ myOptions = options;
+ }
+
+ public JpsLibraryRootImpl(JpsLibraryRootImpl original) {
+ myUrl = original.myUrl;
+ myRootType = original.myRootType;
+ myOptions = original.myOptions;
+ }
+
+ @NotNull
+ @Override
+ public JpsOrderRootType getRootType() {
+ return myRootType;
+ }
+
+ @NotNull
+ public String getUrl() {
+ return myUrl;
+ }
+
+ @NotNull
+ @Override
+ public InclusionOptions getInclusionOptions() {
+ return myOptions;
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryRootImpl createCopy() {
+ return new JpsLibraryRootImpl(this);
+ }
+
+ public void applyChanges(@NotNull JpsLibraryRootImpl modified) {
+ }
+
+ @Override
+ @NotNull
+ public JpsLibrary getLibrary() {
+ return (JpsLibrary)myParent.getParent();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootRole.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootRole.java
new file mode 100644
index 000000000000..736f5865c20a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRootRole.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.JpsLibraryRoot;
+import org.jetbrains.jps.model.library.JpsLibraryRootListener;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryRootRole extends JpsElementChildRoleBase<JpsLibraryRoot> {
+ private final JpsOrderRootType myRootType;
+
+ public JpsLibraryRootRole(@NotNull JpsOrderRootType rootType) {
+ super("library root");
+ myRootType = rootType;
+ }
+
+ @Override
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsLibraryRoot element) {
+ dispatcher.getPublisher(JpsLibraryRootListener.class).rootAdded(element);
+ }
+
+ @Override
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsLibraryRoot element) {
+ dispatcher.getPublisher(JpsLibraryRootListener.class).rootRemoved(element);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ return myRootType.equals(((JpsLibraryRootRole)o).myRootType);
+ }
+
+ @Override
+ public int hashCode() {
+ return myRootType.hashCode();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java
new file mode 100644
index 000000000000..3f462aca57b9
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+/**
+ * @author nik
+ */
+public class JpsSdkReferenceImpl<P extends JpsElement> extends JpsNamedElementReferenceBase<JpsLibrary, JpsTypedLibrary<JpsSdk<P>>, JpsSdkReferenceImpl<P>> implements JpsSdkReference<P> {
+ private final JpsSdkType<P> mySdkType;
+
+ public JpsSdkReferenceImpl(@NotNull String elementName, @NotNull JpsSdkType<P> sdkType,
+ @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
+ super(elementName, parentReference);
+ mySdkType = sdkType;
+ }
+
+ private JpsSdkReferenceImpl(JpsSdkReferenceImpl<P> original) {
+ super(original);
+ mySdkType = original.mySdkType;
+ }
+
+ @NotNull
+ public String getSdkName() {
+ return myElementName;
+ }
+
+ @Override
+ protected JpsTypedLibrary<JpsSdk<P>> resolve(JpsLibrary element) {
+ return element.asTyped(mySdkType);
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkReferenceImpl<P> createCopy() {
+ return new JpsSdkReferenceImpl<P>(this);
+ }
+
+ @Nullable
+ protected JpsElementCollection<? extends JpsLibrary> getCollection(@NotNull JpsCompositeElement parent) {
+ return parent.getContainer().getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/sdk/JpsSdkImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/sdk/JpsSdkImpl.java
new file mode 100644
index 000000000000..c85a377085d0
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/sdk/JpsSdkImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.library.impl.sdk;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.impl.JpsLibraryImpl;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+
+/**
+ * @author nik
+ */
+public class JpsSdkImpl<P extends JpsElement> extends JpsCompositeElementBase<JpsSdkImpl<P>> implements JpsSdk<P> {
+ private final JpsSdkType<P> mySdkType;
+ private String myHomePath;
+ private String myVersionString;
+
+ public JpsSdkImpl(String homePath, String versionString, JpsSdkType<P> type, P properties) {
+ myHomePath = homePath;
+ myVersionString = versionString;
+ mySdkType = type;
+ myContainer.setChild(type.getSdkPropertiesRole(), properties);
+ }
+
+ private JpsSdkImpl(JpsSdkImpl<P> original) {
+ super(original);
+ mySdkType = original.mySdkType;
+ myHomePath = original.myHomePath;
+ myVersionString = original.myVersionString;
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkImpl<P> createCopy() {
+ return new JpsSdkImpl<P>(this);
+ }
+
+ @Override
+ public P getSdkProperties() {
+ return myContainer.getChild(mySdkType.getSdkPropertiesRole());
+ }
+
+ @Override
+ public JpsSdkReference<P> createReference() {
+ return JpsElementFactory.getInstance().createSdkReference(getParent().getName(), mySdkType);
+ }
+
+ @Override
+ public JpsSdkType<P> getSdkType() {
+ return mySdkType;
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryImpl<JpsSdk<P>> getParent() {
+ //noinspection unchecked
+ return (JpsLibraryImpl<JpsSdk<P>>)super.getParent();
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsSdkImpl<P> modified) {
+ super.applyChanges(modified);
+ setHomePath(modified.getHomePath());
+ setVersionString(modified.getVersionString());
+ }
+
+ @Override
+ public String getHomePath() {
+ return myHomePath;
+ }
+
+ @Override
+ public void setHomePath(String homePath) {
+ if (!Comparing.equal(myHomePath, homePath)) {
+ myHomePath = homePath;
+ fireElementChanged();
+ }
+ }
+
+ @Override
+ public String getVersionString() {
+ return myVersionString;
+ }
+
+ @Override
+ public void setVersionString(String versionString) {
+ if (!Comparing.equal(myVersionString, versionString)) {
+ myVersionString = versionString;
+ fireElementChanged();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java
new file mode 100644
index 000000000000..86e248ea1916
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.CollectConsumer;
+import com.intellij.util.Consumer;
+import com.intellij.util.Processor;
+import gnu.trove.THashSet;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.*;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public abstract class JpsDependenciesEnumeratorBase<Self extends JpsDependenciesEnumerator> implements JpsDependenciesEnumerator {
+ private boolean myWithoutSdk;
+ private boolean myWithoutLibraries;
+ protected boolean myWithoutDepModules;
+ private boolean myWithoutModuleSourceEntries;
+ protected boolean myRecursively;
+ protected final Collection<JpsModule> myRootModules;
+ private Condition<JpsDependencyElement> myCondition;
+
+ protected JpsDependenciesEnumeratorBase(Collection<JpsModule> rootModules) {
+ myRootModules = rootModules;
+ }
+
+ @Override
+ public Self withoutLibraries() {
+ myWithoutLibraries = true;
+ return self();
+ }
+
+ @Override
+ public Self withoutDepModules() {
+ myWithoutDepModules = true;
+ return self();
+ }
+
+ @Override
+ public Self withoutSdk() {
+ myWithoutSdk = true;
+ return self();
+ }
+
+ @Override
+ public Self withoutModuleSourceEntries() {
+ myWithoutModuleSourceEntries = true;
+ return self();
+ }
+
+ @Override
+ public Self satisfying(Condition<JpsDependencyElement> condition) {
+ myCondition = condition;
+ return self();
+ }
+
+ @Override
+ public Self recursively() {
+ myRecursively = true;
+ return self();
+ }
+
+ protected abstract Self self();
+
+ @Override
+ public Set<JpsModule> getModules() {
+ Set<JpsModule> result = new HashSet<JpsModule>();
+ processModules(new CollectConsumer<JpsModule>(result));
+ return result;
+ }
+
+ @Override
+ public void processModules(final Consumer<JpsModule> consumer) {
+ processDependencies(new Processor<JpsDependencyElement>() {
+ @Override
+ public boolean process(JpsDependencyElement dependencyElement) {
+ if (myRecursively && dependencyElement instanceof JpsModuleSourceDependency) {
+ consumer.consume(dependencyElement.getContainingModule());
+ }
+ else if ((!myRecursively || !shouldProcessDependenciesRecursively())&& dependencyElement instanceof JpsModuleDependency) {
+ JpsModule module = ((JpsModuleDependency)dependencyElement).getModule();
+ if (module != null) {
+ consumer.consume(module);
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ protected boolean shouldProcessDependenciesRecursively() {
+ return true;
+ }
+
+ public boolean processDependencies(Processor<JpsDependencyElement> processor) {
+ THashSet<JpsModule> processed = new THashSet<JpsModule>();
+ for (JpsModule module : myRootModules) {
+ if (!doProcessDependencies(module, processor, processed)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean doProcessDependencies(JpsModule module, Processor<JpsDependencyElement> processor, Set<JpsModule> processed) {
+ if (!processed.add(module)) return true;
+
+ for (JpsDependencyElement element : module.getDependenciesList().getDependencies()) {
+ if (myCondition != null && !myCondition.value(element)) continue;
+
+ if (myWithoutSdk && element instanceof JpsSdkDependency
+ || myWithoutLibraries && element instanceof JpsLibraryDependency
+ || myWithoutModuleSourceEntries && element instanceof JpsModuleSourceDependency) continue;
+
+ if (myWithoutDepModules) {
+ if (!myRecursively && element instanceof JpsModuleDependency) continue;
+ if (element instanceof JpsModuleSourceDependency && !isEnumerationRootModule(module)) continue;
+ }
+
+ if (!shouldProcess(module, element)) {
+ continue;
+ }
+
+ if (element instanceof JpsModuleDependency) {
+ if (myRecursively && shouldProcessDependenciesRecursively()) {
+ JpsModule depModule = ((JpsModuleDependency)element).getModule();
+ if (depModule != null) {
+ doProcessDependencies(depModule, processor, processed);
+ continue;
+ }
+ }
+ if (myWithoutDepModules) continue;
+ }
+
+ if (!processor.process(element)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean shouldProcess(JpsModule module, JpsDependencyElement element) {
+ return true;
+ }
+
+ public boolean isEnumerationRootModule(JpsModule module) {
+ return myRootModules.contains(module);
+ }
+
+ @Override
+ public Set<JpsLibrary> getLibraries() {
+ Set<JpsLibrary> libraries = new HashSet<JpsLibrary>();
+ processLibraries(new CollectConsumer<JpsLibrary>(libraries));
+ return libraries;
+ }
+
+ public void processLibraries(final Consumer<JpsLibrary> consumer) {
+ processDependencies(new Processor<JpsDependencyElement>() {
+ @Override
+ public boolean process(JpsDependencyElement dependencyElement) {
+ if (dependencyElement instanceof JpsLibraryDependency) {
+ JpsLibrary library = ((JpsLibraryDependency)dependencyElement).getLibrary();
+ if (library != null) {
+ consumer.consume(library);
+ }
+ }
+ return true;
+ }
+ });
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesListImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesListImpl.java
new file mode 100644
index 000000000000..bd447a4f103a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesListImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.*;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsDependenciesListImpl extends JpsCompositeElementBase<JpsDependenciesListImpl> implements JpsDependenciesList {
+ public static final JpsElementCollectionRole<JpsDependencyElement> DEPENDENCY_COLLECTION_ROLE =
+ JpsElementCollectionRole.create(JpsElementChildRoleBase.<JpsDependencyElement>create("dependency"));
+
+ public JpsDependenciesListImpl() {
+ super();
+ myContainer.setChild(DEPENDENCY_COLLECTION_ROLE);
+ }
+
+ private JpsDependenciesListImpl(JpsDependenciesListImpl original) {
+ super(original);
+ }
+
+ @Override
+ @NotNull
+ public List<JpsDependencyElement> getDependencies() {
+ return myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).getElements();
+ }
+
+ @Override
+ public void clear() {
+ myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).removeAllChildren();
+ }
+
+ @Override
+ @NotNull
+ public JpsModuleDependency addModuleDependency(@NotNull JpsModule module) {
+ return addModuleDependency(module.createReference());
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleDependency addModuleDependency(@NotNull JpsModuleReference moduleReference) {
+ final JpsModuleDependencyImpl dependency = new JpsModuleDependencyImpl(moduleReference);
+ myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).addChild(dependency);
+ return dependency;
+ }
+
+ @Override
+ @NotNull
+ public JpsLibraryDependency addLibraryDependency(@NotNull JpsLibrary libraryElement) {
+ return addLibraryDependency(libraryElement.createReference());
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryDependency addLibraryDependency(@NotNull JpsLibraryReference libraryReference) {
+ final JpsLibraryDependencyImpl dependency = new JpsLibraryDependencyImpl(libraryReference);
+ myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).addChild(dependency);
+ return dependency;
+ }
+
+ @Override
+ public void addModuleSourceDependency() {
+ myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).addChild(new JpsModuleSourceDependencyImpl());
+ }
+
+ @Override
+ public void addSdkDependency(@NotNull JpsSdkType<?> sdkType) {
+ myContainer.getChild(DEPENDENCY_COLLECTION_ROLE).addChild(new JpsSdkDependencyImpl(sdkType));
+ }
+
+ @NotNull
+ @Override
+ public JpsDependenciesListImpl createCopy() {
+ return new JpsDependenciesListImpl(this);
+ }
+
+ @Override
+ public JpsModuleImpl getParent() {
+ return (JpsModuleImpl)super.getParent();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesRootsEnumeratorBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesRootsEnumeratorBase.java
new file mode 100644
index 000000000000..36e54c8f4603
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesRootsEnumeratorBase.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import com.intellij.util.CollectConsumer;
+import com.intellij.util.Consumer;
+import com.intellij.util.Processor;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.module.*;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public abstract class JpsDependenciesRootsEnumeratorBase<E extends JpsDependenciesEnumeratorBase<?>> implements JpsDependenciesRootsEnumerator {
+ protected final JpsOrderRootType myRootType;
+ protected final E myDependenciesEnumerator;
+
+ public JpsDependenciesRootsEnumeratorBase(E dependenciesEnumerator, JpsOrderRootType rootType) {
+ myDependenciesEnumerator = dependenciesEnumerator;
+ myRootType = rootType;
+ }
+
+ @Override
+ public Collection<String> getUrls() {
+ Set<String> urls = new LinkedHashSet<String>();
+ processUrls(new CollectConsumer<String>(urls));
+ return urls;
+ }
+
+ @Override
+ public Collection<File> getRoots() {
+ final Set<File> files = new LinkedHashSet<File>();
+ processUrls(new Consumer<String>() {
+ @Override
+ public void consume(String url) {
+ files.add(JpsPathUtil.urlToFile(url));
+ }
+ });
+ return files;
+ }
+
+ private void processUrls(final Consumer<String> urlConsumer) {
+ myDependenciesEnumerator.processDependencies(new Processor<JpsDependencyElement>() {
+ @Override
+ public boolean process(JpsDependencyElement dependencyElement) {
+ if (dependencyElement instanceof JpsModuleSourceDependency) {
+ processModuleRootUrls(dependencyElement.getContainingModule(), dependencyElement, urlConsumer);
+ }
+ else if (dependencyElement instanceof JpsModuleDependency) {
+ JpsModule dep = ((JpsModuleDependency)dependencyElement).getModule();
+ if (dep != null) {
+ processModuleRootUrls(dep, dependencyElement, urlConsumer);
+ }
+ }
+ else if (dependencyElement instanceof JpsLibraryDependency) {
+ JpsLibrary lib = ((JpsLibraryDependency)dependencyElement).getLibrary();
+ if (lib != null) {
+ processLibraryRootUrls(lib, urlConsumer);
+ }
+ }
+ else if (dependencyElement instanceof JpsSdkDependency) {
+ JpsLibrary lib = ((JpsSdkDependency)dependencyElement).resolveSdk();
+ if (lib != null) {
+ processLibraryRootUrls(lib, urlConsumer);
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ private boolean processLibraryRootUrls(JpsLibrary library, Consumer<String> urlConsumer) {
+ for (String url : library.getRootUrls(myRootType)) {
+ urlConsumer.consume(url);
+ }
+ return true;
+ }
+
+ protected abstract boolean processModuleRootUrls(JpsModule module, JpsDependencyElement dependencyElement, Consumer<String> urlConsumer);
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java
new file mode 100644
index 000000000000..f7457b37b1dd
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public abstract class JpsDependencyElementBase<Self extends JpsDependencyElementBase<Self>> extends JpsCompositeElementBase<Self> implements JpsDependencyElement {
+ protected JpsDependencyElementBase() {
+ super();
+ }
+
+ protected JpsDependencyElementBase(JpsDependencyElementBase<Self> original) {
+ super(original);
+ }
+
+ @Override
+ public void remove() {
+ ((JpsDependenciesListImpl)myParent.getParent()).getContainer().getChild(JpsDependenciesListImpl.DEPENDENCY_COLLECTION_ROLE).removeChild(this);
+ }
+
+ public JpsDependenciesListImpl getDependenciesList() {
+ return (JpsDependenciesListImpl)myParent.getParent();
+ }
+
+ @Override
+ public JpsModule getContainingModule() {
+ return getDependenciesList().getParent();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetImpl.java
new file mode 100644
index 000000000000..9822b5b40dcd
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementCollection;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase;
+import org.jetbrains.jps.model.module.JpsFacet;
+import org.jetbrains.jps.model.module.JpsFacetReference;
+import org.jetbrains.jps.model.module.JpsFacetType;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public class JpsFacetImpl extends JpsNamedCompositeElementBase<JpsFacetImpl> implements JpsFacet {
+ private static final JpsElementChildRole<JpsFacetReference> PARENT_FACET_REFERENCE = JpsElementChildRoleBase.create("parent facet");
+ private final JpsFacetType<?> myFacetType;
+
+ public <P extends JpsElement>JpsFacetImpl(JpsFacetType<?> facetType, @NotNull String name, @NotNull P properties) {
+ super(name);
+ myFacetType = facetType;
+ myContainer.setChild(JpsFacetRole.COLLECTION_ROLE);
+ }
+
+ private JpsFacetImpl(JpsFacetImpl original) {
+ super(original);
+ myFacetType = original.myFacetType;
+ }
+
+ @NotNull
+ @Override
+ public JpsFacetImpl createCopy() {
+ return new JpsFacetImpl(this);
+ }
+
+ @Override
+ @NotNull
+ public JpsFacetType<?> getType() {
+ return myFacetType;
+ }
+
+ @Override
+ public void setParentFacet(@NotNull JpsFacet facet) {
+ myContainer.setChild(PARENT_FACET_REFERENCE, facet.createReference());
+ }
+
+ @Override
+ @Nullable
+ public JpsFacet getParentFacet() {
+ final JpsFacetReference reference = myContainer.getChild(PARENT_FACET_REFERENCE);
+ return reference != null ? reference.resolve() : null;
+ }
+
+ @Override
+ public JpsModule getModule() {
+ return myParent != null ? (JpsModule)myParent.getParent() : null;
+ }
+
+ @NotNull
+ @Override
+ public JpsFacetReference createReference() {
+ return new JpsFacetReferenceImpl(getName(), getModule().createReference());
+ }
+
+ @Override
+ public void delete() {
+ //noinspection unchecked
+ ((JpsElementCollection<JpsFacet>)myParent).removeChild(this);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetReferenceImpl.java
new file mode 100644
index 000000000000..a1d9b3593ea0
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetReferenceImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.impl.JpsNamedElementReferenceImpl;
+import org.jetbrains.jps.model.module.JpsFacet;
+import org.jetbrains.jps.model.module.JpsFacetReference;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public class JpsFacetReferenceImpl extends JpsNamedElementReferenceImpl<JpsFacet, JpsFacetReferenceImpl> implements JpsFacetReference {
+ public JpsFacetReferenceImpl(String facetName, JpsModuleReference moduleReference) {
+ super(JpsFacetRole.COLLECTION_ROLE, facetName, moduleReference);
+ }
+
+ private JpsFacetReferenceImpl(JpsFacetReferenceImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsFacetReferenceImpl createCopy() {
+ return new JpsFacetReferenceImpl(this);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetRole.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetRole.java
new file mode 100644
index 000000000000..d59044b60f16
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsFacetRole.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsFacet;
+import org.jetbrains.jps.model.module.JpsFacetListener;
+
+/**
+ * @author nik
+ */
+public class JpsFacetRole extends JpsElementChildRoleBase<JpsFacet> {
+ public static final JpsFacetRole INSTANCE = new JpsFacetRole();
+ public static final JpsElementCollectionRole<JpsFacet> COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE);
+
+ public JpsFacetRole() {
+ super("facet");
+ }
+
+ @Override
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsFacet element) {
+ dispatcher.getPublisher(JpsFacetListener.class).facetAdded(element);
+ }
+
+ @Override
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsFacet element) {
+ dispatcher.getPublisher(JpsFacetListener.class).facetRemoved(element);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsLibraryDependencyImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsLibraryDependencyImpl.java
new file mode 100644
index 000000000000..f0d5ccc7ae9c
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsLibraryDependencyImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.module.JpsLibraryDependency;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryDependencyImpl extends JpsDependencyElementBase<JpsLibraryDependencyImpl> implements JpsLibraryDependency {
+ public static final JpsElementChildRole<JpsLibraryReference>
+ LIBRARY_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("library reference");
+
+ public JpsLibraryDependencyImpl(final JpsLibraryReference reference) {
+ super();
+ myContainer.setChild(LIBRARY_REFERENCE_CHILD_ROLE, reference);
+ }
+
+ public JpsLibraryDependencyImpl(JpsLibraryDependencyImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryReference getLibraryReference() {
+ return myContainer.getChild(LIBRARY_REFERENCE_CHILD_ROLE);
+ }
+
+ @Override
+ public JpsLibrary getLibrary() {
+ return getLibraryReference().resolve();
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryDependencyImpl createCopy() {
+ return new JpsLibraryDependencyImpl(this);
+ }
+
+ @Override
+ public String toString() {
+ return "lib dep [" + getLibraryReference() + "]";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleDependencyImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleDependencyImpl.java
new file mode 100644
index 000000000000..3233fdc7b057
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleDependencyImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import com.intellij.openapi.util.Ref;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleDependency;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public class JpsModuleDependencyImpl extends JpsDependencyElementBase<JpsModuleDependencyImpl> implements JpsModuleDependency {
+ private static final JpsElementChildRole<JpsModuleReference>
+ MODULE_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("module reference");
+
+ private volatile Ref<JpsModule> myCachedModule = null;
+
+ public JpsModuleDependencyImpl(final JpsModuleReference moduleReference) {
+ super();
+ myContainer.setChild(MODULE_REFERENCE_CHILD_ROLE, moduleReference);
+ }
+
+ public JpsModuleDependencyImpl(JpsModuleDependencyImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleReference getModuleReference() {
+ return myContainer.getChild(MODULE_REFERENCE_CHILD_ROLE);
+ }
+
+ @Override
+ public JpsModule getModule() {
+ Ref<JpsModule> moduleRef = myCachedModule;
+ if (moduleRef == null) {
+ moduleRef = new Ref<JpsModule>(getModuleReference().resolve());
+ myCachedModule = moduleRef;
+ }
+ return moduleRef.get();
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleDependencyImpl createCopy() {
+ return new JpsModuleDependencyImpl(this);
+ }
+
+ @Override
+ public String toString() {
+ return "module dep [" + getModuleReference() + "]";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleImpl.java
new file mode 100644
index 000000000000..847affcb3219
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleImpl.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase;
+import org.jetbrains.jps.model.impl.JpsUrlListRole;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryCollection;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.impl.JpsLibraryCollectionImpl;
+import org.jetbrains.jps.model.library.impl.JpsLibraryRole;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.*;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsModuleImpl<P extends JpsElement> extends JpsNamedCompositeElementBase<JpsModuleImpl<P>> implements JpsTypedModule<P> {
+ private static final JpsUrlListRole CONTENT_ROOTS_ROLE = new JpsUrlListRole("content roots");
+ private static final JpsUrlListRole EXCLUDED_ROOTS_ROLE = new JpsUrlListRole("excluded roots");
+ public static final JpsElementChildRole<JpsDependenciesListImpl> DEPENDENCIES_LIST_CHILD_ROLE = JpsElementChildRoleBase.create("dependencies");
+ private final JpsModuleType<P> myModuleType;
+ private final JpsLibraryCollection myLibraryCollection;
+
+ public JpsModuleImpl(JpsModuleType<P> type, @NotNull String name, @NotNull P properties) {
+ super(name);
+ myModuleType = type;
+ myContainer.setChild(myModuleType.getPropertiesRole(), properties);
+ myContainer.setChild(CONTENT_ROOTS_ROLE);
+ myContainer.setChild(EXCLUDED_ROOTS_ROLE);
+ myContainer.setChild(JpsFacetRole.COLLECTION_ROLE);
+ myContainer.setChild(DEPENDENCIES_LIST_CHILD_ROLE, new JpsDependenciesListImpl());
+ getDependenciesList().addModuleSourceDependency();
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.setChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ myContainer.setChild(JpsModuleSourceRootRole.ROOT_COLLECTION_ROLE);
+ myContainer.setChild(JpsSdkReferencesTableImpl.ROLE);
+ }
+
+ private JpsModuleImpl(JpsModuleImpl<P> original) {
+ super(original);
+ myModuleType = original.myModuleType;
+ myLibraryCollection = new JpsLibraryCollectionImpl(myContainer.getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE));
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleImpl<P> createCopy() {
+ return new JpsModuleImpl<P>(this);
+ }
+
+ @Override
+ public JpsElementType<P> getType() {
+ return myModuleType;
+ }
+
+ @Override
+ @NotNull
+ public P getProperties() {
+ return myContainer.getChild(myModuleType.getPropertiesRole());
+ }
+
+ @Override
+ public <P extends JpsElement> JpsTypedModule<P> asTyped(@NotNull JpsModuleType<P> type) {
+ //noinspection unchecked
+ return myModuleType.equals(type) ? (JpsTypedModule<P>)this : null;
+ }
+
+ @NotNull
+ @Override
+ public JpsUrlList getContentRootsList() {
+ return myContainer.getChild(CONTENT_ROOTS_ROLE);
+ }
+
+ @NotNull
+ public JpsUrlList getExcludeRootsList() {
+ return myContainer.getChild(EXCLUDED_ROOTS_ROLE);
+ }
+
+ @NotNull
+ @Override
+ public List<JpsModuleSourceRoot> getSourceRoots() {
+ return myContainer.getChild(JpsModuleSourceRootRole.ROOT_COLLECTION_ROLE).getElements();
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> Iterable<JpsTypedModuleSourceRoot<P>> getSourceRoots(@NotNull JpsModuleSourceRootType<P> type) {
+ return myContainer.getChild(JpsModuleSourceRootRole.ROOT_COLLECTION_ROLE).getElementsOfType(type);
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement, T extends JpsModuleSourceRootType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsModuleSourceRoot addSourceRoot(@NotNull String url, @NotNull T rootType) {
+ return addSourceRoot(url, rootType, rootType.createDefaultProperties());
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> JpsModuleSourceRoot addSourceRoot(@NotNull String url, @NotNull JpsModuleSourceRootType<P> rootType,
+ @NotNull P properties) {
+ final JpsModuleSourceRootImpl root = new JpsModuleSourceRootImpl<P>(url, rootType, properties);
+ return myContainer.getChild(JpsModuleSourceRootRole.ROOT_COLLECTION_ROLE).addChild(root);
+ }
+
+ @Override
+ public void removeSourceRoot(@NotNull String url, @NotNull JpsModuleSourceRootType rootType) {
+ final JpsElementCollection<JpsModuleSourceRoot> roots = myContainer.getChild(JpsModuleSourceRootRole.ROOT_COLLECTION_ROLE);
+ for (JpsModuleSourceRoot root : roots.getElements()) {
+ if (root.getRootType().equals(rootType) && root.getUrl().equals(url)) {
+ roots.removeChild(root);
+ break;
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement> JpsFacet addFacet(@NotNull String name, @NotNull JpsFacetType<P> type, @NotNull P properties) {
+ return myContainer.getChild(JpsFacetRole.COLLECTION_ROLE).addChild(new JpsFacetImpl(type, name, properties));
+ }
+
+ @NotNull
+ @Override
+ public List<JpsFacet> getFacets() {
+ return myContainer.getChild(JpsFacetRole.COLLECTION_ROLE).getElements();
+ }
+
+ @NotNull
+ @Override
+ public JpsDependenciesList getDependenciesList() {
+ return myContainer.getChild(DEPENDENCIES_LIST_CHILD_ROLE);
+ }
+
+ @Override
+ @NotNull
+ public JpsSdkReferencesTable getSdkReferencesTable() {
+ return myContainer.getChild(JpsSdkReferencesTableImpl.ROLE);
+ }
+
+ @Override
+ public <P extends JpsElement> JpsSdkReference<P> getSdkReference(@NotNull JpsSdkType<P> type) {
+ JpsSdkReference<P> sdkReference = getSdkReferencesTable().getSdkReference(type);
+ if (sdkReference != null) {
+ return sdkReference;
+ }
+ JpsProject project = getProject();
+ if (project != null) {
+ return project.getSdkReferencesTable().getSdkReference(type);
+ }
+ return null;
+ }
+
+ @Override
+ public <P extends JpsElement> JpsSdk<P> getSdk(@NotNull JpsSdkType<P> type) {
+ final JpsSdkReference<P> reference = getSdkReference(type);
+ if (reference == null) return null;
+ JpsTypedLibrary<JpsSdk<P>> library = reference.resolve();
+ return library != null ? library.getProperties() : null;
+ }
+
+ @Override
+ public void delete() {
+ //noinspection unchecked
+ ((JpsElementCollection<JpsModule>)myParent).removeChild(this);
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleReference createReference() {
+ return new JpsModuleReferenceImpl(getName());
+ }
+
+ @NotNull
+ @Override
+ public <P extends JpsElement, Type extends JpsLibraryType<P> & JpsElementTypeWithDefaultProperties<P>>
+ JpsLibrary addModuleLibrary(@NotNull String name, @NotNull Type type) {
+ return myLibraryCollection.addLibrary(name, type);
+ }
+
+ @Override
+ public void addModuleLibrary(final @NotNull JpsLibrary library) {
+ myLibraryCollection.addLibrary(library);
+ }
+
+ @NotNull
+ @Override
+ public JpsLibraryCollection getLibraryCollection() {
+ return myLibraryCollection;
+ }
+
+ @Nullable
+ public JpsProject getProject() {
+ JpsModel model = getModel();
+ return model != null ? model.getProject() : null;
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleType<P> getModuleType() {
+ return myModuleType;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleReferenceImpl.java
new file mode 100644
index 000000000000..b0485fd02f92
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleReferenceImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.impl.JpsNamedElementReferenceImpl;
+import org.jetbrains.jps.model.impl.JpsProjectElementReference;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+
+/**
+ * @author nik
+ */
+public class JpsModuleReferenceImpl extends JpsNamedElementReferenceImpl<JpsModule, JpsModuleReferenceImpl> implements JpsModuleReference {
+ public JpsModuleReferenceImpl(String elementName) {
+ super(JpsModuleRole.MODULE_COLLECTION_ROLE, elementName, new JpsProjectElementReference());
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleReferenceImpl createCopy() {
+ return new JpsModuleReferenceImpl(myElementName);
+ }
+
+ @NotNull
+ @Override
+ public String getModuleName() {
+ return myElementName;
+ }
+
+ @Override
+ public JpsModuleReference asExternal(@NotNull JpsModel model) {
+ model.registerExternalReference(this);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "module ref: '" + myElementName + "' in " + getParentReference();
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java
new file mode 100644
index 000000000000..a55659ee85c4
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleListener;
+
+/**
+ * @author nik
+ */
+public class JpsModuleRole extends JpsElementChildRoleBase<JpsModule> {
+ public static final JpsElementChildRole<JpsModule> INSTANCE = new JpsModuleRole();
+ public static final JpsElementCollectionRole<JpsModule> MODULE_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE);
+
+ public JpsModuleRole() {
+ super("module");
+ }
+
+ @Override
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsModule element) {
+ dispatcher.getPublisher(JpsModuleListener.class).moduleAdded(element);
+ }
+
+ @Override
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsModule element) {
+ dispatcher.getPublisher(JpsModuleListener.class).moduleRemoved(element);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceDependencyImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceDependencyImpl.java
new file mode 100644
index 000000000000..a47351ede651
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceDependencyImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModuleSourceDependency;
+
+/**
+ * @author nik
+ */
+public class JpsModuleSourceDependencyImpl extends JpsDependencyElementBase<JpsModuleSourceDependencyImpl>
+ implements JpsModuleSourceDependency {
+ public JpsModuleSourceDependencyImpl() {
+ super();
+ }
+
+ public JpsModuleSourceDependencyImpl(JpsModuleSourceDependencyImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleSourceDependencyImpl createCopy() {
+ return new JpsModuleSourceDependencyImpl(this);
+ }
+
+ @Override
+ public String toString() {
+ return "module source dep";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java
new file mode 100644
index 000000000000..90369b816b4b
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementType;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsModuleSourceRootImpl<P extends JpsElement> extends JpsCompositeElementBase<JpsModuleSourceRootImpl<P>> implements JpsTypedModuleSourceRoot<P> {
+ private final JpsModuleSourceRootType<P> myRootType;
+ private final String myUrl;
+
+ public JpsModuleSourceRootImpl(String url, JpsModuleSourceRootType<P> type, P properties) {
+ super();
+ myRootType = type;
+ myContainer.setChild(type.getPropertiesRole(), properties);
+ myUrl = url;
+ }
+
+ private JpsModuleSourceRootImpl(JpsModuleSourceRootImpl<P> original) {
+ super(original);
+ myRootType = original.myRootType;
+ myUrl = original.myUrl;
+ }
+
+ @Override
+ public <P extends JpsElement> P getProperties(@NotNull JpsModuleSourceRootType<P> type) {
+ if (myRootType.equals(type)) {
+ //noinspection unchecked
+ return (P)myContainer.getChild(myRootType.getPropertiesRole());
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public <P extends JpsElement> JpsTypedModuleSourceRoot<P> asTyped(@NotNull JpsModuleSourceRootType<P> type) {
+ //noinspection unchecked
+ return myRootType.equals(type) ? (JpsTypedModuleSourceRoot<P>)this : null;
+ }
+
+ @Override
+ public JpsElementType<?> getType() {
+ return myRootType;
+ }
+
+ @NotNull
+ @Override
+ public P getProperties() {
+ return myContainer.getChild(myRootType.getPropertiesRole());
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleSourceRootType<P> getRootType() {
+ return myRootType;
+ }
+
+ @NotNull
+ public String getUrl() {
+ return myUrl;
+ }
+
+ @NotNull
+ @Override
+ public File getFile() {
+ return JpsPathUtil.urlToFile(myUrl);
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleSourceRootImpl<P> createCopy() {
+ return new JpsModuleSourceRootImpl<P>(this);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootRole.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootRole.java
new file mode 100644
index 000000000000..d3f087a0722f
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootRole.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEventDispatcher;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.ex.JpsElementCollectionRole;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootListener;
+
+/**
+ * @author nik
+ */
+public class JpsModuleSourceRootRole extends JpsElementChildRoleBase<JpsModuleSourceRoot> {
+ public static final JpsModuleSourceRootRole INSTANCE = new JpsModuleSourceRootRole();
+ public static final JpsElementCollectionRole<JpsModuleSourceRoot> ROOT_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE);
+
+ public JpsModuleSourceRootRole() {
+ super("module source root");
+ }
+
+ @Override
+ public void fireElementAdded(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsModuleSourceRoot element) {
+ dispatcher.getPublisher(JpsModuleSourceRootListener.class).sourceRootAdded(element);
+ }
+
+ @Override
+ public void fireElementRemoved(@NotNull JpsEventDispatcher dispatcher, @NotNull JpsModuleSourceRoot element) {
+ dispatcher.getPublisher(JpsModuleSourceRootListener.class).sourceRootRemoved(element);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java
new file mode 100644
index 000000000000..7b9f1be2ebe6
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.JpsSdkDependency;
+
+/**
+ * @author nik
+ */
+public class JpsSdkDependencyImpl extends JpsDependencyElementBase<JpsSdkDependencyImpl> implements JpsSdkDependency {
+ private final JpsSdkType<?> mySdkType;
+
+ public JpsSdkDependencyImpl(@NotNull JpsSdkType<?> sdkType) {
+ super();
+ mySdkType = sdkType;
+ }
+
+ public JpsSdkDependencyImpl(JpsSdkDependencyImpl original) {
+ super(original);
+ mySdkType = original.mySdkType;
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkDependencyImpl createCopy() {
+ return new JpsSdkDependencyImpl(this);
+ }
+
+ @Override
+ @NotNull
+ public JpsSdkType<?> getSdkType() {
+ return mySdkType;
+ }
+
+ @Override
+ public JpsLibrary resolveSdk() {
+ final JpsSdkReference<?> reference = getSdkReference();
+ if (reference == null) return null;
+ return reference.resolve();
+ }
+
+ @Override
+ @Nullable
+ public JpsSdkReference<?> getSdkReference() {
+ return getContainingModule().getSdkReference(mySdkType);
+ }
+
+ @Override
+ public boolean isInherited() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "sdk dep [" + mySdkType + "]";
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferenceRole.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferenceRole.java
new file mode 100644
index 000000000000..dedba2eebc72
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferenceRole.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+
+public class JpsSdkReferenceRole<P extends JpsElement> extends JpsElementChildRoleBase<JpsSdkReference<P>> {
+ private final JpsSdkType<P> myType;
+
+ public JpsSdkReferenceRole(@NotNull JpsSdkType<P> type) {
+ super("sdk reference " + type);
+ myType = type;
+ }
+
+ @Override
+ public int hashCode() {
+ return myType.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof JpsSdkReferenceRole && myType.equals(((JpsSdkReferenceRole)obj).myType);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferencesTableImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferencesTableImpl.java
new file mode 100644
index 000000000000..adf4bfb7314a
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkReferencesTableImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.module.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementCreator;
+import org.jetbrains.jps.model.ex.JpsCompositeElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.JpsSdkReferencesTable;
+
+/**
+ * @author nik
+ */
+public class JpsSdkReferencesTableImpl extends JpsCompositeElementBase<JpsSdkReferencesTableImpl> implements JpsSdkReferencesTable {
+ public static final JpsSdkReferencesTableRole ROLE = new JpsSdkReferencesTableRole();
+
+ public JpsSdkReferencesTableImpl() {
+ super();
+ }
+
+ private JpsSdkReferencesTableImpl(JpsSdkReferencesTableImpl original) {
+ super(original);
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkReferencesTableImpl createCopy() {
+ return new JpsSdkReferencesTableImpl(this);
+ }
+
+ @Override
+ public <P extends JpsElement> void setSdkReference(@NotNull JpsSdkType<P> type, @Nullable JpsSdkReference<P> sdkReference) {
+ JpsSdkReferenceRole<P> role = new JpsSdkReferenceRole<P>(type);
+ if (sdkReference != null) {
+ myContainer.setChild(role, sdkReference);
+ }
+ else {
+ myContainer.removeChild(role);
+ }
+ }
+
+ @Override
+ public <P extends JpsElement> JpsSdkReference<P> getSdkReference(@NotNull JpsSdkType<P> type) {
+ return myContainer.getChild(new JpsSdkReferenceRole<P>(type));
+ }
+
+ private static class JpsSdkReferencesTableRole extends JpsElementChildRoleBase<JpsSdkReferencesTable> implements JpsElementCreator<JpsSdkReferencesTable> {
+ public JpsSdkReferencesTableRole() {
+ super("sdk references");
+ }
+
+ @NotNull
+ @Override
+ public JpsSdkReferencesTable create() {
+ return new JpsSdkReferencesTableImpl();
+ }
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java b/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java
new file mode 100644
index 000000000000..750469071360
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.service.impl;
+
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author nik
+ */
+public class JpsServiceManagerImpl extends JpsServiceManager {
+ private final ConcurrentHashMap<Class, Object> myServices = new ConcurrentHashMap<Class, Object>();
+ private final ConcurrentHashMap<Class, List<?>> myExtensions = new ConcurrentHashMap<Class, List<?>>();
+
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ //noinspection unchecked
+ T service = (T)myServices.get(serviceClass);
+ if (service == null) {
+ final Iterator<T> iterator = ServiceLoader.load(serviceClass, serviceClass.getClassLoader()).iterator();
+ if (!iterator.hasNext()) {
+ throw new ServiceConfigurationError("Implementation for " + serviceClass + " not found");
+ }
+ service = iterator.next();
+ if (iterator.hasNext()) {
+ throw new ServiceConfigurationError(
+ "More than one implementation for " + serviceClass + " found: " + service.getClass() + " and " + iterator.next().getClass());
+ }
+ myServices.putIfAbsent(serviceClass, service);
+ //noinspection unchecked
+ service = (T)myServices.get(serviceClass);
+ }
+ return service;
+ }
+
+ @Override
+ public <T> Iterable<T> getExtensions(Class<T> extensionClass) {
+ List<?> cached = myExtensions.get(extensionClass);
+ if (cached == null) {
+ final ServiceLoader<T> loader = ServiceLoader.load(extensionClass, extensionClass.getClassLoader());
+ List<T> extensions = new ArrayList<T>();
+ for (T t : loader) {
+ extensions.add(t);
+ }
+ myExtensions.putIfAbsent(extensionClass, extensions);
+ cached = myExtensions.get(extensionClass);
+ }
+ //noinspection unchecked
+ return (List<T>)cached;
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/service/impl/SharedThreadPoolImpl.java b/jps/model-impl/src/org/jetbrains/jps/service/impl/SharedThreadPoolImpl.java
new file mode 100644
index 000000000000..b4bd1eb947e2
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/service/impl/SharedThreadPoolImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.service.impl;
+
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * @author nik
+ */
+public class SharedThreadPoolImpl extends SharedThreadPool {
+ private final ExecutorService myService = Executors.newCachedThreadPool();
+
+ @Override
+ public void execute(Runnable command) {
+ executeOnPooledThread(command);
+ }
+
+ @Override
+ public Future<?> executeOnPooledThread(final Runnable action) {
+ return myService.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ action.run();
+ }
+ finally {
+ Thread.interrupted(); // reset interrupted status
+ }
+ }
+ });
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java
new file mode 100644
index 000000000000..744077ab89fc
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.jps.util.JpsPathUtil;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.library.JpsTypedLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsLibraryDependency;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+
+/**
+ * @author nik
+ */
+public class JpsDependenciesEnumeratorTest extends JpsJavaModelTestCase {
+ private JpsTypedLibrary<JpsSdk<JpsDummyElement>> myJdk;
+ private JpsModule myModule;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ File home = PathManagerEx.findFileUnderCommunityHome("java/mockJDK-1.7");
+ myJdk = myModel.getGlobal().addSdk("mockJDK-1.7", home.getAbsolutePath(), "1.7", JpsJavaSdkType.INSTANCE);
+ myJdk.addRoot(getRtJar(), JpsOrderRootType.COMPILED);
+ myModule = addModule();
+ myModule.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, myJdk.getProperties().createReference());
+ myModule.getDependenciesList().addSdkDependency(JpsJavaSdkType.INSTANCE);
+ }
+
+ public void testLibrary() throws Exception {
+ JpsModuleRootModificationUtil.addDependency(myModule, createJDomLibrary());
+
+ assertClassRoots(orderEntries(myModule), getRtJar(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().productionOnly().runtimeOnly(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutLibraries(), getRtJar());
+ assertSourceRoots(orderEntries(myModule), getJDomSources());
+ }
+
+ private String getJDomSources() {
+ return getJarUrlFromLibDir("src/jdom.zip");
+ }
+
+ private String getJDomJar() {
+ return getJarUrlFromLibDir("jdom.jar");
+ }
+
+ private String getAsmJar() {
+ return getJarUrlFromLibDir("asm.jar");
+ }
+
+ private String getJarUrlFromLibDir(final String relativePath) {
+ return JpsPathUtil.getLibraryRootUrl(PathManager.findFileInLibDirectory(relativePath));
+ }
+
+ private String getRtJar() {
+ return JpsPathUtil.getLibraryRootUrl(PathManagerEx.findFileUnderCommunityHome("java/mockJDK-1.7/jre/lib/rt.jar"));
+ }
+
+ private JpsLibrary createJDomLibrary() {
+ JpsLibrary library = addLibrary("jdom");
+ library.addRoot(getJDomJar(), JpsOrderRootType.COMPILED);
+ library.addRoot(getJDomSources(), JpsOrderRootType.SOURCES);
+ return library;
+ }
+
+ private JpsLibrary createAsmLibrary() {
+ JpsLibrary library = addLibrary("asm");
+ library.addRoot(getAsmJar(), JpsOrderRootType.COMPILED);
+ return library;
+ }
+
+ public void testModuleSources() throws Exception {
+ final String srcRoot = addSourceRoot(myModule, false);
+ final String testRoot = addSourceRoot(myModule, true);
+ final String output = setModuleOutput(myModule, false);
+ final String testOutput = setModuleOutput(myModule, true);
+
+ assertClassRoots(orderEntries(myModule).withoutSdk(), testOutput, output);
+ assertClassRoots(orderEntries(myModule).withoutSdk().productionOnly(), output);
+ assertSourceRoots(orderEntries(myModule), srcRoot, testRoot);
+ assertSourceRoots(orderEntries(myModule).productionOnly(), srcRoot);
+
+ assertEnumeratorRoots(orderEntries(myModule).withoutSdk().classes().withoutSelfModuleOutput(), output);
+ assertEnumeratorRoots(orderEntries(myModule).withoutSdk().productionOnly().classes().withoutSelfModuleOutput());
+ }
+
+ public void testLibraryScope() throws Exception {
+ JpsLibraryDependency dependency = myModule.getDependenciesList().addLibraryDependency(createJDomLibrary());
+ getJavaService().getOrCreateDependencyExtension(dependency).setScope(JpsJavaDependencyScope.RUNTIME);
+ JpsModuleRootModificationUtil.addDependency(myModule, createJDomLibrary(), JpsJavaDependencyScope.RUNTIME, false);
+
+ assertClassRoots(orderEntries(myModule).withoutSdk(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().exportedOnly());
+ assertClassRoots(orderEntries(myModule).withoutSdk().compileOnly());
+ }
+
+ public void testModuleDependency() throws Exception {
+ final JpsModule dep = addModule("dep");
+ final String depSrcRoot = addSourceRoot(dep, false);
+ final String depTestRoot = addSourceRoot(dep, true);
+ final String depOutput = setModuleOutput(dep, false);
+ final String depTestOutput = setModuleOutput(dep, true);
+ JpsModuleRootModificationUtil.addDependency(dep, createJDomLibrary(), JpsJavaDependencyScope.COMPILE, true);
+ JpsModuleRootModificationUtil.addDependency(myModule, dep, JpsJavaDependencyScope.COMPILE, true);
+
+ final String srcRoot = addSourceRoot(myModule, false);
+ final String testRoot = addSourceRoot(myModule, true);
+ final String output = setModuleOutput(myModule, false);
+ final String testOutput = setModuleOutput(myModule, true);
+
+ assertClassRoots(orderEntries(myModule).withoutSdk(), testOutput, output, depTestOutput, depOutput);
+ assertClassRoots(orderEntries(myModule).withoutSdk().recursively(), testOutput, output, depTestOutput, depOutput, getJDomJar());
+ assertSourceRoots(orderEntries(myModule), srcRoot, testRoot, depSrcRoot, depTestRoot);
+ assertSourceRoots(orderEntries(myModule).recursively(), srcRoot, testRoot, depSrcRoot, depTestRoot, getJDomSources());
+
+ assertClassRoots(orderEntries(myModule).withoutSdk().withoutModuleSourceEntries().recursively(), getJDomJar());
+ assertSourceRoots(orderEntries(myModule).withoutSdk().withoutModuleSourceEntries().recursively(), getJDomSources());
+ assertEnumeratorRoots(orderEntries(myModule).withoutSdk().withoutModuleSourceEntries().recursively().classes(), getJDomJar());
+ assertEnumeratorRoots(orderEntries(myModule).withoutSdk().withoutModuleSourceEntries().recursively().sources(), getJDomSources());
+
+ assertEnumeratorRoots(orderEntries(myModule).withoutSdk().recursively().classes().withoutSelfModuleOutput(),
+ output, depTestOutput, depOutput, getJDomJar());
+ assertEnumeratorRoots(orderEntries(myModule).productionOnly().withoutSdk().recursively().classes().withoutSelfModuleOutput(),
+ depOutput, getJDomJar());
+
+ assertClassRoots(orderEntries(myModule).withoutSdk().withoutDepModules().withoutModuleSourceEntries().recursively(), getJDomJar());
+ assertEnumeratorRoots(
+ orderEntries(myModule).productionOnly().withoutSdk().withoutDepModules().withoutModuleSourceEntries().recursively().classes(),
+ getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().withoutDepModules().withoutModuleSourceEntries());
+ assertEnumeratorRoots(orderEntries(myModule).productionOnly().withoutModuleSourceEntries().withoutSdk().withoutDepModules().classes());
+ }
+
+ public void testModuleJpsJavaDependencyScope() throws Exception {
+ final JpsModule dep = addModule("dep");
+ JpsModuleRootModificationUtil.addDependency(dep, createJDomLibrary(), JpsJavaDependencyScope.COMPILE, true);
+ JpsModuleRootModificationUtil.addDependency(myModule, dep, JpsJavaDependencyScope.TEST, true);
+
+ assertClassRoots(orderEntries(myModule).withoutSdk());
+ assertClassRoots(orderEntries(myModule).withoutSdk().recursively(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().exportedOnly().recursively(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().productionOnly().recursively());
+
+ assertClassRoots(orderEntries(myProject).withoutSdk(), getJDomJar());
+ assertClassRoots(orderEntries(myProject).withoutSdk().productionOnly(), getJDomJar());
+ }
+
+ public void testNotExportedLibrary() throws Exception {
+ final JpsModule dep = addModule("dep");
+ JpsModuleRootModificationUtil.addDependency(dep, createJDomLibrary(), JpsJavaDependencyScope.COMPILE, false);
+ JpsModuleRootModificationUtil.addDependency(myModule, createAsmLibrary(), JpsJavaDependencyScope.COMPILE, false);
+ JpsModuleRootModificationUtil.addDependency(myModule, dep, JpsJavaDependencyScope.COMPILE, false);
+
+ assertClassRoots(orderEntries(myModule).withoutSdk(), getAsmJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().recursively(), getAsmJar(), getJDomJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().recursively().exportedOnly(), getAsmJar());
+ assertClassRoots(orderEntries(myModule).withoutSdk().exportedOnly().recursively());
+ }
+
+ public void testJdkIsNotExported() throws Exception {
+ assertClassRoots(orderEntries(myModule).exportedOnly());
+ }
+
+ public void testProject() throws Exception {
+ JpsModuleRootModificationUtil.addDependency(myModule, createJDomLibrary());
+
+ final String srcRoot = addSourceRoot(myModule, false);
+ final String testRoot = addSourceRoot(myModule, true);
+ final String output = setModuleOutput(myModule, false);
+ final String testOutput = setModuleOutput(myModule, true);
+
+ assertClassRoots(orderEntries(myProject).withoutSdk(), testOutput, output, getJDomJar());
+ assertSourceRoots(orderEntries(myProject).withoutSdk(), srcRoot, testRoot, getJDomSources());
+ }
+
+ public void testModules() throws Exception {
+ JpsModuleRootModificationUtil.addDependency(myModule, createJDomLibrary());
+
+ final String srcRoot = addSourceRoot(myModule, false);
+ final String testRoot = addSourceRoot(myModule, true);
+ final String output = setModuleOutput(myModule, false);
+ final String testOutput = setModuleOutput(myModule, true);
+
+ assertClassRoots(getJavaService().enumerateDependencies(Arrays.asList(myModule)).withoutSdk(),
+ testOutput, output, getJDomJar());
+ assertSourceRoots(getJavaService().enumerateDependencies(Arrays.asList(myModule)).withoutSdk(),
+ srcRoot, testRoot, getJDomSources());
+ }
+
+ private String setModuleOutput(JpsModule module, boolean tests) {
+ try {
+ File file = FileUtil.createTempDirectory(module.getName(), tests ? "testSrc" : "src");
+ JpsJavaModuleExtension extension = getJavaService().getOrCreateModuleExtension(module);
+ String url = JpsPathUtil.getLibraryRootUrl(file);
+ if (tests) {
+ extension.setTestOutputUrl(url);
+ }
+ else {
+ extension.setOutputUrl(url);
+ }
+ return url;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String addSourceRoot(JpsModule module, boolean tests) {
+ try {
+ File file = FileUtil.createTempDirectory(module.getName(), tests ? "testSrc" : "src");
+ return module.addSourceRoot(JpsPathUtil.getLibraryRootUrl(file), tests ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE).getUrl();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private JpsJavaDependenciesEnumerator orderEntries(JpsProject project) {
+ return JpsJavaExtensionService.dependencies(project);
+ }
+
+ private static JpsJavaDependenciesEnumerator orderEntries(JpsModule module) {
+ return JpsJavaExtensionService.dependencies(module);
+ }
+
+ private static void assertClassRoots(final JpsJavaDependenciesEnumerator enumerator, String... urls) {
+ assertEnumeratorRoots(enumerator.classes(), urls);
+ }
+
+ private static void assertSourceRoots(final JpsJavaDependenciesEnumerator enumerator, String... urls) {
+ assertEnumeratorRoots(enumerator.sources(), urls);
+ }
+
+ private static void assertEnumeratorRoots(JpsJavaDependenciesRootsEnumerator rootsEnumerator, String... urls) {
+ assertOrderedEquals(rootsEnumerator.getUrls(), urls);
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsFacetTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsFacetTest.java
new file mode 100644
index 000000000000..7c1f7ae95ea7
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsFacetTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.jps.model.java.JpsJavaModuleType;
+import org.jetbrains.jps.model.module.JpsFacet;
+import org.jetbrains.jps.model.module.JpsFacetType;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public class JpsFacetTest extends JpsModelTestCase {
+ public void testAddFacet() {
+ final JpsModule m = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ m.addFacet("f", MY_FACET_TYPE, JpsElementFactory.getInstance().createDummyElement());
+ assertEquals("f", assertOneElement(m.getFacets()).getName());
+ }
+
+ public void testCreateReferenceByFacet() {
+ final JpsFacet facet = myProject.addModule("m", JpsJavaModuleType.INSTANCE).addFacet("f", MY_FACET_TYPE, JpsElementFactory.getInstance().createDummyElement());
+ final JpsElementReference<JpsFacet> reference = facet.createReference().asExternal(myModel);
+ assertSame(facet, reference.resolve());
+ }
+
+ private static final JpsFacetType<JpsDummyElement> MY_FACET_TYPE = new JpsFacetType<JpsDummyElement>() { };
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaExtensionTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaExtensionTest.java
new file mode 100644
index 000000000000..3a767aff764b
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaExtensionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsLibraryDependency;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsJavaExtensionTest extends JpsJavaModelTestCase {
+ public void testModule() {
+ final JpsModule module = addModule();
+ final JpsJavaModuleExtension extension = getJavaService().getOrCreateModuleExtension(module);
+ extension.setOutputUrl("file://path");
+ JpsJavaModuleExtension moduleExtension = getJavaService().getModuleExtension(module);
+ assertNotNull(moduleExtension);
+ assertEquals("file://path", moduleExtension.getOutputUrl());
+ }
+
+ public void testDependency() {
+ final JpsModel model = myModel.createModifiableModel(new TestJpsEventDispatcher());
+ final JpsModule module = model.getProject().addModule("m", JpsJavaModuleType.INSTANCE);
+ final JpsLibrary library = model.getProject().addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ final JpsLibraryDependency dependency = module.getDependenciesList().addLibraryDependency(library);
+ getJavaService().getOrCreateDependencyExtension(dependency).setScope(JpsJavaDependencyScope.TEST);
+ getJavaService().getOrCreateDependencyExtension(dependency).setExported(true);
+ model.commit();
+
+ List<JpsDependencyElement> dependencies = assertOneElement(myProject.getModules()).getDependenciesList().getDependencies();
+ assertEquals(2, dependencies.size());
+ final JpsDependencyElement dep = dependencies.get(1);
+ final JpsJavaDependencyExtension extension = getJavaService().getDependencyExtension(dep);
+ assertNotNull(extension);
+ assertTrue(extension.isExported());
+ assertSame(JpsJavaDependencyScope.TEST, extension.getScope());
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaModelTestCase.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaModelTestCase.java
new file mode 100644
index 000000000000..bd8cd6baf613
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsJavaModelTestCase.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaLibraryType;
+import org.jetbrains.jps.model.java.JpsJavaModuleType;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public abstract class JpsJavaModelTestCase extends JpsModelTestCase {
+ protected JpsModule addModule() {
+ return addModule("m");
+ }
+
+ protected JpsModule addModule(final String name) {
+ return myProject.addModule(name, JpsJavaModuleType.INSTANCE);
+ }
+
+ protected JpsLibrary addLibrary() {
+ return addLibrary("l");
+ }
+
+ protected JpsLibrary addLibrary(final String name) {
+ return myProject.addLibrary(name, JpsJavaLibraryType.INSTANCE);
+ }
+
+ protected JpsJavaExtensionService getJavaService() {
+ return JpsJavaExtensionService.getInstance();
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsLibraryTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsLibraryTest.java
new file mode 100644
index 000000000000..324fe6e06dfd
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsLibraryTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.jps.model.java.JpsJavaLibraryType;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.*;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryTest extends JpsModelTestCase {
+ public void testAddLibrary() {
+ JpsLibrary a = myProject.addLibrary("a", JpsJavaLibraryType.INSTANCE);
+ JpsLibraryCollection collection = myProject.getLibraryCollection();
+ assertSameElements(collection.getLibraries(), a);
+ assertSameElements(ContainerUtilRt.newArrayList(collection.getLibraries(JpsJavaLibraryType.INSTANCE)), a);
+ assertEmpty(ContainerUtilRt.newArrayList(collection.getLibraries(JpsJavaSdkType.INSTANCE)));
+ }
+
+ public void testAddRoot() {
+ final JpsLibrary library = myProject.addLibrary("a", JpsJavaLibraryType.INSTANCE);
+ library.addRoot("file://my-url", JpsOrderRootType.COMPILED);
+ assertEquals("file://my-url", assertOneElement(library.getRoots(JpsOrderRootType.COMPILED)).getUrl());
+ }
+
+ public void testModifiableCopy() {
+ myProject.addLibrary("a", JpsJavaLibraryType.INSTANCE);
+
+ final JpsModel modifiableModel = myModel.createModifiableModel(new TestJpsEventDispatcher());
+ final JpsLibrary modifiable = assertOneElement(modifiableModel.getProject().getLibraryCollection().getLibraries());
+ modifiable.addRoot("file://my-url", JpsOrderRootType.COMPILED);
+ modifiableModel.commit();
+
+ final JpsLibrary library = assertOneElement(myProject.getLibraryCollection().getLibraries());
+ assertEquals("file://my-url", assertOneElement(library.getRoots(JpsOrderRootType.COMPILED)).getUrl());
+ assertEmpty(library.getRoots(JpsOrderRootType.SOURCES));
+ }
+
+ public void testCreateReferenceByLibrary() {
+ final JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ final JpsLibraryReference reference = library.createReference().asExternal(myModel);
+ assertEquals("l", reference.getLibraryName());
+ assertSame(library, reference.resolve());
+ }
+
+ public void testCreateReferenceByName() {
+ JpsLibraryReference reference = JpsElementFactory.getInstance().createLibraryReference("l", myProject.createReference()).asExternal(myModel);
+ assertEquals("l", reference.getLibraryName());
+ assertNull(reference.resolve());
+
+ final JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ assertSame(library, reference.resolve());
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModelTestCase.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModelTestCase.java
new file mode 100644
index 000000000000..3bf9b25f0bcd
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModelTestCase.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import com.intellij.testFramework.UsefulTestCase;
+import org.jetbrains.jps.model.impl.JpsModelImpl;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModelTestCase extends UsefulTestCase {
+ protected JpsModel myModel;
+ protected TestJpsEventDispatcher myDispatcher;
+ protected JpsProject myProject;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ myDispatcher = new TestJpsEventDispatcher();
+ myModel = new JpsModelImpl(myDispatcher);
+ myProject = myModel.getProject();
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleRootModificationUtil.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleRootModificationUtil.java
new file mode 100644
index 000000000000..4a92bdb3008e
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleRootModificationUtil.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JpsJavaDependencyExtension;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+/**
+ * @author nik
+ */
+public class JpsModuleRootModificationUtil {
+ public static void addDependency(JpsModule module, JpsLibrary library) {
+ addDependency(module, library, JpsJavaDependencyScope.COMPILE, false);
+ }
+
+ public static void addDependency(JpsModule module, JpsLibrary library, final JpsJavaDependencyScope scope, final boolean exported) {
+ setDependencyProperties(module.getDependenciesList().addLibraryDependency(library), scope, exported);
+ }
+
+ private static void setDependencyProperties(JpsDependencyElement dependency, JpsJavaDependencyScope scope, boolean exported) {
+ JpsJavaDependencyExtension extension = JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency);
+ extension.setExported(exported);
+ extension.setScope(scope);
+ }
+
+ public static void setModuleSdk(JpsModule module, @Nullable JpsSdk<JpsDummyElement> sdk) {
+ module.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, sdk != null ? sdk.createReference() : null);
+ }
+
+ public static void setSdkInherited(JpsModule module) {
+ module.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, null);
+ }
+
+ public static void addDependency(final JpsModule from, final JpsModule to) {
+ addDependency(from, to, JpsJavaDependencyScope.COMPILE, false);
+ }
+
+ public static void addDependency(final JpsModule from, final JpsModule to, final JpsJavaDependencyScope scope, final boolean exported) {
+ setDependencyProperties(from.getDependenciesList().addModuleDependency(to), scope, exported);
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleTest.java
new file mode 100644
index 000000000000..58ca33824813
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsModuleTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.module.*;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsModuleTest extends JpsModelTestCase {
+ public void testAddSourceRoot() {
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ JpsSimpleElement<JavaSourceRootProperties> properties = JpsElementFactory.getInstance().createSimpleElement(
+ new JavaSourceRootProperties("com.xxx"));
+ final JpsModuleSourceRoot sourceRoot = module.addSourceRoot("file://url", JavaSourceRootType.SOURCE, properties);
+
+ assertSameElements(myDispatcher.retrieveAdded(JpsModule.class), module);
+ assertSameElements(myDispatcher.retrieveAdded(JpsModuleSourceRoot.class), sourceRoot);
+
+ final JpsModuleSourceRoot root = assertOneElement(module.getSourceRoots());
+ assertEquals("file://url", root.getUrl());
+ assertSameElements(ContainerUtilRt.newArrayList(module.getSourceRoots(JavaSourceRootType.SOURCE)), root);
+ assertEmpty(ContainerUtil.newArrayList(module.getSourceRoots(JavaSourceRootType.TEST_SOURCE)));
+ JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> typedRoot = root.asTyped(JavaSourceRootType.SOURCE);
+ assertNotNull(typedRoot);
+ assertEquals("com.xxx", typedRoot.getProperties().getData().getPackagePrefix());
+ }
+
+ public void testGetModulesOfType() {
+ JpsProject project = myProject;
+ JpsModule module = project.addModule("m", JpsJavaModuleType.INSTANCE);
+ Iterable<JpsTypedModule<JpsDummyElement>> modules = project.getModules(JpsJavaModuleType.INSTANCE);
+ assertSameElements(ContainerUtil.newArrayList(modules), module);
+ }
+
+ public void testModifiableModel() {
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ final JpsModuleSourceRoot root0 = module.addSourceRoot("url1", JavaSourceRootType.SOURCE);
+ myDispatcher.clear();
+
+ final JpsModel modifiableModel = myModel.createModifiableModel(new TestJpsEventDispatcher());
+ final JpsModule modifiableModule = assertOneElement(modifiableModel.getProject().getModules());
+ modifiableModule.addSourceRoot("url2", JavaSourceRootType.TEST_SOURCE);
+ modifiableModel.commit();
+
+ assertEmpty(myDispatcher.retrieveAdded(JpsModule.class));
+ assertEmpty(myDispatcher.retrieveRemoved(JpsModule.class));
+
+ final List<? extends JpsModuleSourceRoot> roots = module.getSourceRoots();
+ assertEquals(2, roots.size());
+ assertSame(root0, roots.get(0));
+ final JpsModuleSourceRoot root1 = roots.get(1);
+ assertEquals("url2", root1.getUrl());
+ assertOrderedEquals(myDispatcher.retrieveAdded(JpsModuleSourceRoot.class), root1);
+ assertEmpty(myDispatcher.retrieveChanged(JpsModuleSourceRoot.class));
+ }
+
+ public void testAddDependency() {
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ final JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ final JpsModule dep = myProject.addModule("dep", JpsJavaModuleType.INSTANCE);
+ module.getDependenciesList().addLibraryDependency(library);
+ module.getDependenciesList().addModuleDependency(dep);
+
+ final List<? extends JpsDependencyElement> dependencies = module.getDependenciesList().getDependencies();
+ assertEquals(3, dependencies.size());
+ assertInstanceOf(dependencies.get(0), JpsModuleSourceDependency.class);
+ assertSame(library, assertInstanceOf(dependencies.get(1), JpsLibraryDependency.class).getLibrary());
+ assertSame(dep, assertInstanceOf(dependencies.get(2), JpsModuleDependency.class).getModule());
+ }
+
+ public void testChangeElementInModifiableModel() {
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ final JpsModule dep = myProject.addModule("dep", JpsJavaModuleType.INSTANCE);
+ final JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
+ module.getDependenciesList().addLibraryDependency(library);
+ myDispatcher.clear();
+
+ final JpsModel modifiableModel = myModel.createModifiableModel(new TestJpsEventDispatcher());
+ final JpsModule m = modifiableModel.getProject().getModules().get(0);
+ assertEquals("m", m.getName());
+ m.getDependenciesList().getDependencies().get(1).remove();
+ m.getDependenciesList().addModuleDependency(dep);
+ modifiableModel.commit();
+ assertOneElement(myDispatcher.retrieveRemoved(JpsLibraryDependency.class));
+ assertSame(dep, assertOneElement(myDispatcher.retrieveAdded(JpsModuleDependency.class)).getModuleReference().resolve());
+ List<JpsDependencyElement> dependencies = module.getDependenciesList().getDependencies();
+ assertEquals(2, dependencies.size());
+ assertSame(dep, assertInstanceOf(dependencies.get(1), JpsModuleDependency.class).getModuleReference().resolve());
+ }
+
+ public void testCreateReferenceByModule() {
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ final JpsModuleReference reference = module.createReference().asExternal(myModel);
+ assertEquals("m", reference.getModuleName());
+ assertSame(module, reference.resolve());
+ }
+
+ public void testCreateReferenceByName() {
+ final JpsModuleReference reference = JpsElementFactory.getInstance().createModuleReference("m").asExternal(myModel);
+ assertEquals("m", reference.getModuleName());
+ assertNull(reference.resolve());
+
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ assertSame(module, reference.resolve());
+ }
+
+ public void testSdkDependency() {
+ JpsSdk<JpsDummyElement> sdk = myModel.getGlobal().addSdk("sdk", null, null, JpsJavaSdkType.INSTANCE).getProperties();
+ final JpsModule module = myProject.addModule("m", JpsJavaModuleType.INSTANCE);
+ module.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, sdk.createReference());
+ module.getDependenciesList().addSdkDependency(JpsJavaSdkType.INSTANCE);
+
+ List<JpsDependencyElement> dependencies = module.getDependenciesList().getDependencies();
+ assertEquals(2, dependencies.size());
+ final JpsSdkDependency dependency = assertInstanceOf(dependencies.get(1), JpsSdkDependency.class);
+ assertSame(sdk.getParent(), dependency.resolveSdk());
+ }
+}
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/TestJpsEventDispatcher.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/TestJpsEventDispatcher.java
new file mode 100644
index 000000000000..4d9de8706eae
--- /dev/null
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/TestJpsEventDispatcher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.impl.JpsEventDispatcherBase;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+class TestJpsEventDispatcher extends JpsEventDispatcherBase implements JpsEventDispatcher {
+ private List<JpsElement> myAdded = new ArrayList<JpsElement>();
+ private List<JpsElement> myRemoved = new ArrayList<JpsElement>();
+ private List<JpsElement> myChanged = new ArrayList<JpsElement>();
+
+ @Override
+ public <T extends JpsElement> void fireElementAdded(@NotNull T element, @NotNull JpsElementChildRole<T> role) {
+ super.fireElementAdded(element, role);
+ myAdded.add(element);
+ }
+
+ @Override
+ public <T extends JpsElement> void fireElementRemoved(@NotNull T element, @NotNull JpsElementChildRole<T> role) {
+ super.fireElementRemoved(element, role);
+ myRemoved.add(element);
+ }
+
+ @Override
+ public void fireElementChanged(@NotNull JpsElement element) {
+ myChanged.add(element);
+ }
+
+ @Override
+ public void fireElementRenamed(@NotNull JpsNamedElement element, @NotNull String oldName, @NotNull String newName) {
+ }
+
+ public <T extends JpsElement> List<T> retrieveAdded(Class<T> type) {
+ return retrieve(type, myAdded);
+ }
+
+ public <T extends JpsElement> List<T> retrieveRemoved(Class<T> type) {
+ return retrieve(type, myRemoved);
+ }
+
+ public <T extends JpsElement> List<T> retrieveChanged(Class<T> type) {
+ return retrieve(type, myChanged);
+ }
+
+ public void clear() {
+ myAdded.clear();
+ myRemoved.clear();
+ myChanged.clear();
+ }
+
+
+ private static <T extends JpsElement> List<T> retrieve(Class<T> type, List<JpsElement> list) {
+ final List<T> result = new ArrayList<T>();
+ final Iterator<JpsElement> iterator = list.iterator();
+ while (iterator.hasNext()) {
+ JpsElement element = iterator.next();
+ if (type.isInstance(element)) {
+ result.add(type.cast(element));
+ iterator.remove();
+ }
+ }
+ return result;
+ }
+}
diff --git a/jps/model-serialization/jps-model-serialization.iml b/jps/model-serialization/jps-model-serialization.iml
new file mode 100644
index 000000000000..2738e97f2275
--- /dev/null
+++ b/jps/model-serialization/jps-model-serialization.iml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="library" exported="" name="JDOM" level="project" />
+ <orderEntry type="module" module-name="jps-model-impl" exported="" scope="TEST" />
+ <orderEntry type="module" module-name="testFramework" exported="" scope="TEST" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/jps/model-serialization/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
new file mode 100644
index 000000000000..b68edbaed243
--- /dev/null
+++ b/jps/model-serialization/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
@@ -0,0 +1,2 @@
+org.jetbrains.jps.model.serialization.java.JpsJavaModelSerializerExtension
+org.jetbrains.jps.model.serialization.JpsEncodingModelSerializerExtension \ No newline at end of file
diff --git a/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java b/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java
new file mode 100644
index 000000000000..e5f4ca26e492
--- /dev/null
+++ b/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.application;
+
+import org.jdom.Attribute;
+import org.jdom.Text;
+
+/**
+ * Allows to disable expansion of path macros in the values of certain properties.
+ *
+ * @author yole
+ */
+public abstract class PathMacroFilter {
+
+ public boolean skipPathMacros(Text element) {
+ return false;
+ }
+
+ public boolean skipPathMacros(Attribute attribute) {
+ return false;
+ }
+
+ public boolean recursePathMacros(Text element) {
+ return false;
+ }
+
+ public boolean recursePathMacros(Attribute attribute) {
+ return false;
+ }
+}
diff --git a/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java b/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java
new file mode 100644
index 000000000000..ac018718bbaa
--- /dev/null
+++ b/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.components;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.ContainerUtilRt;
+
+import java.util.Map;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: Dec 6, 2004
+ */
+public class ExpandMacroToPathMap extends PathMacroMap {
+ private final Map<String, String> myPlainMap = ContainerUtilRt.newLinkedHashMap();
+ private final Map<String, String> myMacroExpands = ContainerUtil.newHashMap();
+
+ public void addMacroExpand(String macroName, String path) {
+ myMacroExpands.put(macroName, PathMacroMap.quotePath(path));
+ }
+
+ public void put(String fromText, String toText) {
+ myPlainMap.put(fromText, toText);
+ }
+
+ public void putAll(ExpandMacroToPathMap another) {
+ myPlainMap.putAll(another.myPlainMap);
+ myMacroExpands.putAll(another.myMacroExpands);
+ }
+
+ public String substitute(String text, boolean caseSensitive) {
+ if (text == null) {
+ //noinspection ConstantConditions
+ return null;
+ }
+
+ for (Map.Entry<String, String> entry : myPlainMap.entrySet()) {
+ // when replacing macros with actual paths the replace utility may be used as always 'case-sensitive'
+ // for case-insensitive file systems there will be no unnecessary toLowerCase() transforms.
+ text = StringUtil.replace(text, entry.getKey(), entry.getValue(), false);
+ }
+
+ for (String macroName : myMacroExpands.keySet()) {
+ text = replaceMacro(text, macroName, myMacroExpands.get(macroName));
+ }
+
+ return text;
+ }
+
+ private static String replaceMacro(String text, String macroName, String replacement) {
+ while (true) {
+ int start = findMacroIndex(text, macroName);
+ if (start < 0) {
+ break;
+ }
+
+ int end = start + macroName.length() + 2;
+ int slashCount = getSlashCount(text, end);
+ String actualReplacement = slashCount > 0 && !replacement.endsWith("/") ? replacement + "/" : replacement;
+ text = StringUtil.replaceSubstring(text, new TextRange(start, end + slashCount), actualReplacement);
+ }
+ return text;
+ }
+
+ private static int getSlashCount(String text, int pos) {
+ return StringUtil.isChar(text, pos, '/') ? StringUtil.isChar(text, pos + 1, '/') ? 2 : 1 : 0;
+ }
+
+ private static int findMacroIndex(String text, String macroName) {
+ int i = -1;
+ while (true) {
+ i = text.indexOf('$', i + 1);
+ if (i < 0) {
+ return -1;
+ }
+ if (StringUtil.startsWith(text, i + 1, macroName) && StringUtil.isChar(text, i + macroName.length() + 1, '$')) {
+ return i;
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return myPlainMap.hashCode() + myMacroExpands.hashCode();
+ }
+}
diff --git a/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java b/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java
new file mode 100644
index 000000000000..c0484d6299fa
--- /dev/null
+++ b/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.components;
+
+import com.intellij.openapi.application.PathMacroFilter;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jdom.Attribute;
+import org.jdom.Comment;
+import org.jdom.Element;
+import org.jdom.Text;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Eugene Zhuravlev
+ * @since Dec 6, 2004
+ */
+public abstract class PathMacroMap {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.PathMacroMap");
+
+
+ public abstract String substitute(String text, boolean caseSensitive);
+
+ public final void substitute(Element e, boolean caseSensitive) {
+ substitute(e, caseSensitive, false);
+ }
+
+ public final void substitute(Element e, boolean caseSensitive, final boolean recursively,
+ @Nullable PathMacroFilter filter) {
+ List content = e.getContent();
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, contentSize = content.size(); i < contentSize; i++) {
+ Object child = content.get(i);
+ if (child instanceof Element) {
+ Element element = (Element)child;
+ substitute(element, caseSensitive, recursively, filter);
+ }
+ else if (child instanceof Text) {
+ Text t = (Text)child;
+ if (filter == null || !filter.skipPathMacros(t)) {
+ t.setText((recursively || (filter != null && filter.recursePathMacros(t)))
+ ? substituteRecursively(t.getText(), caseSensitive)
+ : substitute(t.getText(), caseSensitive));
+ }
+ }
+ else if (!(child instanceof Comment)) {
+ LOG.error("Wrong content: " + child.getClass());
+ }
+ }
+
+ List attributes = e.getAttributes();
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, attributesSize = attributes.size(); i < attributesSize; i++) {
+ Object attribute1 = attributes.get(i);
+ Attribute attribute = (Attribute)attribute1;
+ if (filter == null || !filter.skipPathMacros(attribute)) {
+ final String value = (recursively || (filter != null && filter.recursePathMacros(attribute)))
+ ? substituteRecursively(attribute.getValue(), caseSensitive)
+ : substitute(attribute.getValue(), caseSensitive);
+ attribute.setValue(value);
+ }
+ }
+ }
+
+ public final void substitute(Element e, boolean caseSensitive, final boolean recursively) {
+ substitute(e, caseSensitive, recursively, null);
+ }
+
+ public String substituteRecursively(String text, boolean caseSensitive) {
+ return substitute(text, caseSensitive);
+ }
+
+ protected static String quotePath(String path) {
+ return FileUtil.toSystemIndependentName(path);
+ }
+
+ public abstract int hashCode();
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JDomSerializationUtil.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JDomSerializationUtil.java
new file mode 100644
index 000000000000..3352b195c499
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JDomSerializationUtil.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.util.JDOMUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class JDomSerializationUtil {
+ @NonNls protected static final String COMPONENT_ELEMENT = "component";
+ @NonNls protected static final String OPTION_ELEMENT = "option";
+ @NonNls protected static final String NAME_ATTRIBUTE = "name";
+ @NonNls protected static final String VALUE_ATTRIBUTE = "value";
+
+ @Nullable
+ public static Element findComponent(@Nullable Element root, @NonNls String componentName) {
+ for (Element element : JDOMUtil.getChildren(root, COMPONENT_ELEMENT)) {
+ if (element.getAttributeValue(NAME_ATTRIBUTE).equals(componentName)) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ public static Element createComponentElement(final String componentName) {
+ final Element element = new Element(COMPONENT_ELEMENT);
+ element.setAttribute(NAME_ATTRIBUTE, componentName);
+ return element;
+ }
+
+ @NotNull
+ public static Element findOrCreateComponentElement(@NotNull Element root, @NotNull String componentName) {
+ Element component = findComponent(root, componentName);
+ if (component == null) {
+ component = createComponentElement(componentName);
+ addComponent(root, component);
+ }
+ return component;
+ }
+
+ public static void addComponent(final Element root, final Element component) {
+ String componentName = component.getAttributeValue(NAME_ATTRIBUTE);
+ final Element old = findComponent(root, componentName);
+ if (old != null) {
+ root.removeContent(old);
+ }
+
+ for (int i = 0; i < root.getContent().size(); i++) {
+ Object o = root.getContent().get(i);
+ if (o instanceof Element) {
+ Element element = (Element)o;
+ if (element.getName().equals(COMPONENT_ELEMENT)) {
+ final String name = element.getAttributeValue(NAME_ATTRIBUTE);
+ if (componentName.compareTo(name) < 0) {
+ root.addContent(i, component);
+ return;
+ }
+ }
+ }
+ }
+ root.addContent(component);
+ }
+
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementExtensionSerializerBase.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementExtensionSerializerBase.java
new file mode 100644
index 000000000000..3c13de8f85a0
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementExtensionSerializerBase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementExtensionSerializerBase<E extends JpsElement> {
+ protected final String myConfigFileName;
+ protected final String myComponentName;
+
+ protected JpsElementExtensionSerializerBase(@Nullable String configFileName, @NotNull String componentName) {
+ myComponentName = componentName;
+ myConfigFileName = configFileName;
+ }
+
+ @Nullable
+ public String getConfigFileName() {
+ return myConfigFileName;
+ }
+
+ @NotNull
+ public String getComponentName() {
+ return myComponentName;
+ }
+
+ public abstract void loadExtension(@NotNull E e, @NotNull Element componentTag);
+
+ // called when no corresponding component tag was found in xml configs
+ public void loadExtensionWithDefaultSettings(@NotNull E e) {
+ }
+
+ public abstract void saveExtension(@NotNull E e, @NotNull Element componentTag);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementPropertiesSerializer.java
new file mode 100644
index 000000000000..0105e539d931
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsElementPropertiesSerializer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+/**
+ * @author nik
+ */
+public abstract class JpsElementPropertiesSerializer<P, Type> {
+ private final String myTypeId;
+ private final Type myType;
+
+ public JpsElementPropertiesSerializer(Type type, String typeId) {
+ myType = type;
+ myTypeId = typeId;
+ }
+
+ public String getTypeId() {
+ return myTypeId;
+ }
+
+ public Type getType() {
+ return myType;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsEncodingModelSerializerExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsEncodingModelSerializerExtension.java
new file mode 100644
index 000000000000..191423c1b099
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsEncodingModelSerializerExtension.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsGlobal;
+import org.jetbrains.jps.model.JpsProject;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsEncodingModelSerializerExtension extends JpsModelSerializerExtension {
+ @NotNull
+ @Override
+ public List<? extends JpsProjectExtensionSerializer> getProjectExtensionSerializers() {
+ return Arrays.asList(new JpsEncodingConfigurationSerializer());
+ }
+
+ @NotNull
+ @Override
+ public List<? extends JpsGlobalExtensionSerializer> getGlobalExtensionSerializers() {
+ return Arrays.asList(new JpsGlobalEncodingSerializer());
+ }
+
+ private static class JpsEncodingConfigurationSerializer extends JpsProjectExtensionSerializer {
+ private JpsEncodingConfigurationSerializer() {
+ super("encodings.xml", "Encoding");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ String projectEncoding = null;
+ Map<String, String> urlToEncoding = new HashMap<String, String>();
+ for (Element fileTag : JDOMUtil.getChildren(componentTag, "file")) {
+ String url = fileTag.getAttributeValue("url");
+ String encoding = fileTag.getAttributeValue("charset");
+ if (url.equals("PROJECT")) {
+ projectEncoding = encoding;
+ }
+ else {
+ urlToEncoding.put(url, encoding);
+ }
+ }
+ JpsEncodingConfigurationService.getInstance().setEncodingConfiguration(project, projectEncoding, urlToEncoding);
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+ }
+
+ private static class JpsGlobalEncodingSerializer extends JpsGlobalExtensionSerializer {
+ public static final String ENCODING_ATTRIBUTE = "default_encoding";
+
+ private JpsGlobalEncodingSerializer() {
+ super("encoding.xml", "Encoding");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ String encoding = componentTag.getAttributeValue(ENCODING_ATTRIBUTE);
+ JpsEncodingConfigurationService.getInstance().setGlobalEncoding(global, StringUtil.nullize(encoding));
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ componentTag.setAttribute(ENCODING_ATTRIBUTE, JpsEncodingConfigurationService.getInstance().getGlobalEncoding(global));
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalExtensionSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalExtensionSerializer.java
new file mode 100644
index 000000000000..2ede7d48e524
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalExtensionSerializer.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsGlobal;
+
+/**
+ * @author nik
+ */
+public abstract class JpsGlobalExtensionSerializer extends JpsElementExtensionSerializerBase<JpsGlobal> {
+ protected JpsGlobalExtensionSerializer(@Nullable String configFileName, @NotNull String componentName) {
+ super(configFileName, componentName);
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java
new file mode 100644
index 000000000000..2f2057082c4c
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsGlobal;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsGlobalLoader extends JpsLoaderBase {
+ public static final String SDK_TABLE_COMPONENT_NAME = "ProjectJdkTable";
+ private static final JpsElementChildRole<JpsSimpleElement<Map<String, String>>> PATH_VARIABLES_ROLE = JpsElementChildRoleBase.create("path variables");
+ private static final JpsGlobalExtensionSerializer[] SERIALIZERS = {
+ new GlobalLibrariesSerializer(), new SdkTableSerializer(), new FileTypesSerializer()
+ };
+ private final JpsGlobal myGlobal;
+
+ public JpsGlobalLoader(JpsGlobal global, Map<String, String> pathVariables) {
+ super(new JpsMacroExpander(pathVariables));
+ myGlobal = global;
+ global.getContainer().setChild(PATH_VARIABLES_ROLE, JpsElementFactory.getInstance().createSimpleElement(pathVariables));
+ }
+
+ public static void loadGlobalSettings(JpsGlobal global, Map<String, String> pathVariables, String optionsPath) throws IOException {
+ File optionsDir = new File(FileUtil.toCanonicalPath(optionsPath));
+ new JpsGlobalLoader(global, pathVariables).load(optionsDir);
+ }
+
+ @Nullable
+ public static String getPathVariable(JpsGlobal global, String name) {
+ JpsSimpleElement<Map<String, String>> child = global.getContainer().getChild(PATH_VARIABLES_ROLE);
+ return child != null ? child.getData().get(name) : null;
+ }
+
+ private void load(File optionsDir) {
+ for (JpsGlobalExtensionSerializer serializer : SERIALIZERS) {
+ loadGlobalComponents(optionsDir, serializer);
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsGlobalExtensionSerializer serializer : extension.getGlobalExtensionSerializers()) {
+ loadGlobalComponents(optionsDir, serializer);
+ }
+ }
+ }
+
+ private void loadGlobalComponents(File optionsDir, JpsGlobalExtensionSerializer serializer) {
+ loadComponents(optionsDir, "other.xml", serializer, myGlobal);
+ }
+
+ private static class GlobalLibrariesSerializer extends JpsGlobalExtensionSerializer {
+ private GlobalLibrariesSerializer() {
+ super("applicationLibraries.xml", "libraryTable");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ JpsLibraryTableSerializer.loadLibraries(componentTag, global.getLibraryCollection());
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ JpsLibraryTableSerializer.saveLibraries(global.getLibraryCollection(), componentTag);
+ }
+ }
+
+ private static class SdkTableSerializer extends JpsGlobalExtensionSerializer {
+ private SdkTableSerializer() {
+ super("jdk.table.xml", SDK_TABLE_COMPONENT_NAME);
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ JpsSdkTableSerializer.loadSdks(componentTag, global.getLibraryCollection());
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ JpsSdkTableSerializer.saveSdks(global.getLibraryCollection(), componentTag);
+ }
+ }
+
+ private static class FileTypesSerializer extends JpsGlobalExtensionSerializer {
+ private FileTypesSerializer() {
+ super("filetypes.xml", "FileTypeManager");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ Element ignoreFilesTag = componentTag.getChild("ignoreFiles");
+ if (ignoreFilesTag != null) {
+ global.getFileTypesConfiguration().setIgnoredPatternString(ignoreFilesTag.getAttributeValue("list"));
+ }
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java
new file mode 100644
index 000000000000..bda75b69ac7a
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jetbrains.jps.model.JpsElement;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public abstract class JpsLoaderBase {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.model.serialization.JpsLoaderBase");
+ private final JpsMacroExpander myMacroExpander;
+
+ protected JpsLoaderBase(JpsMacroExpander macroExpander) {
+ myMacroExpander = macroExpander;
+ }
+
+ protected Element loadRootElement(final File file) {
+ return loadRootElement(file, myMacroExpander);
+ }
+
+ protected <E extends JpsElement> void loadComponents(File dir,
+ final String defaultFileName,
+ JpsElementExtensionSerializerBase<E> serializer,
+ final E element) {
+ String fileName = serializer.getConfigFileName();
+ File configFile = new File(dir, fileName != null ? fileName : defaultFileName);
+ Element componentTag;
+ if (configFile.exists()) {
+ componentTag = JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
+ }
+ else {
+ componentTag = null;
+ }
+
+ if (componentTag != null) {
+ serializer.loadExtension(element, componentTag);
+ }
+ else {
+ serializer.loadExtensionWithDefaultSettings(element);
+ }
+ }
+
+ protected static Element loadRootElement(final File file, final JpsMacroExpander macroExpander) {
+ try {
+ final Element element = JDOMUtil.loadDocument(file).getRootElement();
+ macroExpander.substitute(element, SystemInfo.isFileSystemCaseSensitive);
+ return element;
+ }
+ catch (JDOMException e) {
+ throw new RuntimeException("Cannot parse xml file " + file.getAbsolutePath() + ": " + e.getMessage(), e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Cannot read file " + file.getAbsolutePath() + ": " + e.getMessage(), e);
+ }
+ }
+
+ protected static boolean isXmlFile(File file) {
+ return file.isFile() && FileUtil.getExtension(file.getName()).equalsIgnoreCase("xml");
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsMacroExpander.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsMacroExpander.java
new file mode 100644
index 000000000000..e3d83bad6d73
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsMacroExpander.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.components.ExpandMacroToPathMap;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsMacroExpander {
+ private ExpandMacroToPathMap myExpandMacroMap;
+
+ public JpsMacroExpander(Map<String, String> pathVariables) {
+ myExpandMacroMap = new ExpandMacroToPathMap();
+ for (Map.Entry<String, String> entry : pathVariables.entrySet()) {
+ addMacro(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public void addFileHierarchyReplacements(String macroName, File file) {
+ doAddFileHierarchyReplacements("$" + macroName + "$", file);
+ }
+
+ protected void addMacro(String macroName, String path) {
+ myExpandMacroMap.addMacroExpand(macroName, path);
+ }
+
+ private void doAddFileHierarchyReplacements(String macro, @Nullable File file) {
+ if (file == null) return;
+ doAddFileHierarchyReplacements(macro + "/..", file.getParentFile());
+
+ final String path = FileUtil.toSystemIndependentName(file.getPath());
+ if (StringUtil.endsWithChar(path, '/')) {
+ myExpandMacroMap.put(macro + "/", path);
+ myExpandMacroMap.put(macro, path.substring(0, path.length()-1));
+ }
+ else {
+ myExpandMacroMap.put(macro, path);
+ }
+ }
+
+ public void substitute(Element element, boolean caseSensitive) {
+ myExpandMacroMap.substitute(element, caseSensitive);
+ }
+
+ public ExpandMacroToPathMap getExpandMacroMap() {
+ return myExpandMacroMap;
+ }
+
+ public String substitute(String element, boolean caseSensitive) {
+ return myExpandMacroMap.substitute(element, caseSensitive);
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializationDataService.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializationDataService.java
new file mode 100644
index 000000000000..07efe413868c
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializationDataService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.impl.JpsModuleSerializationDataExtensionImpl;
+import org.jetbrains.jps.model.serialization.impl.JpsProjectSerializationDataExtensionImpl;
+import org.jetbrains.jps.model.serialization.module.JpsModuleSerializationDataExtension;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsModelSerializationDataService {
+
+ @Nullable
+ public static JpsProjectSerializationDataExtension getProjectExtension(@NotNull JpsProject project) {
+ return project.getContainer().getChild(JpsProjectSerializationDataExtensionImpl.ROLE);
+ }
+
+ @Nullable
+ public static File getBaseDirectory(@NotNull JpsProject project) {
+ JpsProjectSerializationDataExtension extension = getProjectExtension(project);
+ return extension != null ? extension.getBaseDirectory() : null;
+ }
+
+ @Nullable
+ public static JpsModuleSerializationDataExtension getModuleExtension(@NotNull JpsModule project) {
+ return project.getContainer().getChild(JpsModuleSerializationDataExtensionImpl.ROLE);
+ }
+
+ @Nullable
+ public static File getBaseDirectory(@NotNull JpsModule module) {
+ JpsModuleSerializationDataExtension extension = getModuleExtension(module);
+ return extension != null ? extension.getBaseDirectory() : null;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java
new file mode 100644
index 000000000000..1f0e599c16b6
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactExtensionSerializer;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
+import org.jetbrains.jps.model.serialization.artifact.JpsPackagingElementSerializer;
+import org.jetbrains.jps.model.serialization.facet.JpsFacetConfigurationSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryPropertiesSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryRootTypeSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsSdkPropertiesSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModuleClasspathSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModulePropertiesSerializer;
+import org.jetbrains.jps.model.serialization.runConfigurations.JpsRunConfigurationPropertiesSerializer;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModelSerializerExtension {
+ public static Iterable<JpsModelSerializerExtension> getExtensions() {
+ return JpsServiceManager.getInstance().getExtensions(JpsModelSerializerExtension.class);
+ }
+
+ public void loadRootModel(@NotNull JpsModule module, @NotNull Element rootModel) {
+ }
+
+ public void saveRootModel(@NotNull JpsModule module, @NotNull Element rootModel) {
+ }
+
+ public void loadModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+ }
+
+ public void saveModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+ }
+
+ public List<JpsLibraryRootTypeSerializer> getLibraryRootTypeSerializers() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<JpsLibraryRootTypeSerializer> getSdkRootTypeSerializers() {
+ return Collections.emptyList();
+ }
+
+ public void loadModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ }
+
+ public void saveModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ }
+
+ @Nullable
+ public JpsElementReference<? extends JpsCompositeElement> createLibraryTableReference(String tableLevel) {
+ return null;
+ }
+
+ @Nullable
+ public String getLibraryTableLevelId(JpsElementReference<? extends JpsCompositeElement> reference) {
+ return null;
+ }
+
+ @NotNull
+ public List<? extends JpsProjectExtensionSerializer> getProjectExtensionSerializers() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends JpsGlobalExtensionSerializer> getGlobalExtensionSerializers() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends JpsModulePropertiesSerializer<?>> getModulePropertiesSerializers() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends JpsLibraryPropertiesSerializer<?>> getLibraryPropertiesSerializers() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public List<? extends JpsSdkPropertiesSerializer<?>> getSdkPropertiesSerializers() {
+ return Collections.emptyList();
+ }
+
+ public List<? extends JpsFacetConfigurationSerializer<?>> getFacetConfigurationSerializers() {
+ return Collections.emptyList();
+ }
+
+ public List<? extends JpsPackagingElementSerializer<?>> getPackagingElementSerializers() {
+ return Collections.emptyList();
+ }
+
+ public List<? extends JpsArtifactPropertiesSerializer<?>> getArtifactTypePropertiesSerializers() {
+ return Collections.emptyList();
+ }
+
+ public List<? extends JpsArtifactExtensionSerializer<?>> getArtifactExtensionSerializers() {
+ return Collections.emptyList();
+ }
+
+ @Nullable
+ public JpsModuleClasspathSerializer getClasspathSerializer() {
+ return null;
+ }
+
+ @NotNull
+ public List<? extends JpsRunConfigurationPropertiesSerializer<?>> getRunConfigurationPropertiesSerializers() {
+ return Collections.emptyList();
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectExtensionSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectExtensionSerializer.java
new file mode 100644
index 000000000000..59fb1e953068
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectExtensionSerializer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsProject;
+
+/**
+ * @author nik
+ */
+public abstract class JpsProjectExtensionSerializer extends JpsElementExtensionSerializerBase<JpsProject> {
+ public static final String WORKSPACE_FILE = "workspace.xml";
+
+ /**
+ * @param configFileName name of file in .idea directory where the extension settings are stored
+ * @param componentName name of the component
+ */
+ public JpsProjectExtensionSerializer(@Nullable String configFileName, @NotNull String componentName) {
+ super(configFileName, componentName);
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java
new file mode 100644
index 000000000000..28863f900152
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.concurrency.BoundedTaskExecutor;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaModuleType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactSerializer;
+import org.jetbrains.jps.model.serialization.facet.JpsFacetSerializer;
+import org.jetbrains.jps.model.serialization.impl.JpsModuleSerializationDataExtensionImpl;
+import org.jetbrains.jps.model.serialization.impl.JpsProjectSerializationDataExtensionImpl;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModuleClasspathSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModulePropertiesSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer;
+import org.jetbrains.jps.model.serialization.runConfigurations.JpsRunConfigurationSerializer;
+import org.jetbrains.jps.service.SharedThreadPool;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * @author nik
+ */
+public class JpsProjectLoader extends JpsLoaderBase {
+ private static final Logger LOG = Logger.getInstance(JpsProjectLoader.class);
+ private static final BoundedTaskExecutor ourThreadPool = new BoundedTaskExecutor(SharedThreadPool.getInstance(), Runtime.getRuntime().availableProcessors());
+ public static final String CLASSPATH_ATTRIBUTE = "classpath";
+ public static final String CLASSPATH_DIR_ATTRIBUTE = "classpath-dir";
+ private final JpsProject myProject;
+ private final Map<String, String> myPathVariables;
+
+ private JpsProjectLoader(JpsProject project, Map<String, String> pathVariables, File baseDir) {
+ super(createProjectMacroExpander(pathVariables, baseDir));
+ myProject = project;
+ myPathVariables = pathVariables;
+ myProject.getContainer().setChild(JpsProjectSerializationDataExtensionImpl.ROLE, new JpsProjectSerializationDataExtensionImpl(baseDir));
+ }
+
+ static JpsMacroExpander createProjectMacroExpander(Map<String, String> pathVariables, File baseDir) {
+ final JpsMacroExpander expander = new JpsMacroExpander(pathVariables);
+ expander.addFileHierarchyReplacements(PathMacroUtil.PROJECT_DIR_MACRO_NAME, baseDir);
+ return expander;
+ }
+
+ public static void loadProject(final JpsProject project, Map<String, String> pathVariables, String projectPath) throws IOException {
+ File file = new File(FileUtil.toCanonicalPath(projectPath));
+ if (file.isFile() && projectPath.endsWith(".ipr")) {
+ new JpsProjectLoader(project, pathVariables, file.getParentFile()).loadFromIpr(file);
+ }
+ else {
+ File directory;
+ if (file.isDirectory() && file.getName().equals(PathMacroUtil.DIRECTORY_STORE_NAME)) {
+ directory = file;
+ }
+ else {
+ directory = new File(file, PathMacroUtil.DIRECTORY_STORE_NAME);
+ if (!directory.isDirectory()) {
+ throw new IOException("Cannot find IntelliJ IDEA project files at " + projectPath);
+ }
+ }
+ new JpsProjectLoader(project, pathVariables, directory.getParentFile()).loadFromDirectory(directory);
+ }
+ }
+
+ public static String getDirectoryBaseProjectName(File dir) {
+ File nameFile = new File(dir, ".name");
+ if (nameFile.isFile()) {
+ try {
+ return FileUtilRt.loadFile(nameFile).trim();
+ }
+ catch (IOException ignored) {
+ }
+ }
+ return StringUtil.replace(dir.getParentFile().getName(), ":", "");
+ }
+
+ private void loadFromDirectory(File dir) {
+ myProject.setName(getDirectoryBaseProjectName(dir));
+ JpsSdkType<?> projectSdkType = loadProjectRoot(loadRootElement(new File(dir, "misc.xml")));
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsProjectExtensionSerializer serializer : extension.getProjectExtensionSerializers()) {
+ loadComponents(dir, "misc.xml", serializer, myProject);
+ }
+ }
+ loadModules(loadRootElement(new File(dir, "modules.xml")), projectSdkType);
+ for (File libraryFile : listXmlFiles(new File(dir, "libraries"))) {
+ loadProjectLibraries(loadRootElement(libraryFile));
+ }
+ for (File artifactFile : listXmlFiles(new File(dir, "artifacts"))) {
+ loadArtifacts(loadRootElement(artifactFile));
+ }
+
+ if (hasRunConfigurationSerializers()) {
+ for (File configurationFile : listXmlFiles(new File(dir, "runConfigurations"))) {
+ JpsRunConfigurationSerializer.loadRunConfigurations(myProject, loadRootElement(configurationFile));
+ }
+ File workspaceFile = new File(dir, "workspace.xml");
+ if (workspaceFile.exists()) {
+ Element runManager = JDomSerializationUtil.findComponent(loadRootElement(workspaceFile), "RunManager");
+ JpsRunConfigurationSerializer.loadRunConfigurations(myProject, runManager);
+ }
+ }
+ }
+
+ private static boolean hasRunConfigurationSerializers() {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ if (!extension.getRunConfigurationPropertiesSerializers().isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NotNull
+ private static File[] listXmlFiles(final File dir) {
+ File[] files = dir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return isXmlFile(file);
+ }
+ });
+ return files != null ? files : ArrayUtil.EMPTY_FILE_ARRAY;
+ }
+
+ private void loadFromIpr(File iprFile) {
+ final Element iprRoot = loadRootElement(iprFile);
+
+ String projectName = FileUtil.getNameWithoutExtension(iprFile);
+ myProject.setName(projectName);
+ File iwsFile = new File(iprFile.getParent(), projectName + ".iws");
+ Element iwsRoot = iwsFile.exists() ? loadRootElement(iwsFile) : null;
+
+ JpsSdkType<?> projectSdkType = loadProjectRoot(iprRoot);
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsProjectExtensionSerializer serializer : extension.getProjectExtensionSerializers()) {
+ Element rootTag = JpsProjectExtensionSerializer.WORKSPACE_FILE.equals(serializer.getConfigFileName()) ? iwsRoot : iprRoot;
+ Element component = JDomSerializationUtil.findComponent(rootTag, serializer.getComponentName());
+ if (component != null) {
+ serializer.loadExtension(myProject, component);
+ }
+ else {
+ serializer.loadExtensionWithDefaultSettings(myProject);
+ }
+ }
+ }
+ loadModules(iprRoot, projectSdkType);
+ loadProjectLibraries(JDomSerializationUtil.findComponent(iprRoot, "libraryTable"));
+ loadArtifacts(JDomSerializationUtil.findComponent(iprRoot, "ArtifactManager"));
+ if (hasRunConfigurationSerializers()) {
+ JpsRunConfigurationSerializer.loadRunConfigurations(myProject, JDomSerializationUtil.findComponent(iprRoot, "ProjectRunConfigurationManager"));
+ JpsRunConfigurationSerializer.loadRunConfigurations(myProject, JDomSerializationUtil.findComponent(iwsRoot, "RunManager"));
+ }
+ }
+
+ private void loadArtifacts(@Nullable Element artifactManagerComponent) {
+ JpsArtifactSerializer.loadArtifacts(myProject, artifactManagerComponent);
+ }
+
+ @Nullable
+ private JpsSdkType<?> loadProjectRoot(Element root) {
+ JpsSdkType<?> sdkType = null;
+ Element rootManagerElement = JDomSerializationUtil.findComponent(root, "ProjectRootManager");
+ if (rootManagerElement != null) {
+ String sdkName = rootManagerElement.getAttributeValue("project-jdk-name");
+ String sdkTypeId = rootManagerElement.getAttributeValue("project-jdk-type");
+ if (sdkName != null) {
+ sdkType = JpsSdkTableSerializer.getSdkType(sdkTypeId);
+ JpsSdkTableSerializer.setSdkReference(myProject.getSdkReferencesTable(), sdkName, sdkType);
+ }
+ }
+ return sdkType;
+ }
+
+ private void loadProjectLibraries(@Nullable Element libraryTableElement) {
+ JpsLibraryTableSerializer.loadLibraries(libraryTableElement, myProject.getLibraryCollection());
+ }
+
+ private void loadModules(Element root, final @Nullable JpsSdkType<?> projectSdkType) {
+ Element componentRoot = JDomSerializationUtil.findComponent(root, "ProjectModuleManager");
+ if (componentRoot == null) return;
+ final Element modules = componentRoot.getChild("modules");
+ List<Future<JpsModule>> futures = new ArrayList<Future<JpsModule>>();
+ final List<String> paths = new ArrayList<String>();
+ final List<String> classpathDirs = new ArrayList<String>();
+ for (Element moduleElement : JDOMUtil.getChildren(modules, "module")) {
+ final String path = moduleElement.getAttributeValue("filepath");
+ final File file = new File(path);
+ if (!file.exists()) {
+ LOG.info("Module '" + FileUtil.getNameWithoutExtension(file) + "' is skipped: " + file.getAbsolutePath() + " doesn't exist");
+ continue;
+ }
+
+ final JpsMacroExpander expander = createModuleMacroExpander(myPathVariables, file);
+ final Element moduleRoot = loadRootElement(file, expander);
+ final String classpathDir = moduleRoot.getAttributeValue(CLASSPATH_DIR_ATTRIBUTE);
+ if (classpathDir != null) {
+ classpathDirs.add(classpathDir);
+ }
+ paths.add(path);
+ }
+ for (final String path : paths) {
+ futures.add(ourThreadPool.submit(new Callable<JpsModule>() {
+ @Override
+ public JpsModule call() throws Exception {
+ return loadModule(path, classpathDirs, projectSdkType);
+ }
+ }));
+ }
+ try {
+ for (Future<JpsModule> future : futures) {
+ JpsModule module = future.get();
+ if (module != null) {
+ myProject.addModule(module);
+ }
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Nullable
+ private JpsModule loadModule(@NotNull String path, List<String> paths, @Nullable JpsSdkType<?> projectSdkType) {
+ final File file = new File(path);
+ String name = FileUtil.getNameWithoutExtension(file);
+ if (!file.exists()) {
+ LOG.info("Module '" + name + "' is skipped: " + file.getAbsolutePath() + " doesn't exist");
+ return null;
+ }
+
+ final JpsMacroExpander expander = createModuleMacroExpander(myPathVariables, file);
+ final Element moduleRoot = loadRootElement(file, expander);
+ final String typeId = moduleRoot.getAttributeValue("type");
+ final JpsModulePropertiesSerializer<?> serializer = getModulePropertiesSerializer(typeId);
+ final JpsModule module = createModule(name, moduleRoot, serializer);
+ module.getContainer().setChild(JpsModuleSerializationDataExtensionImpl.ROLE,
+ new JpsModuleSerializationDataExtensionImpl(file.getParentFile()));
+
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ extension.loadModuleOptions(module, moduleRoot);
+ }
+
+ String baseModulePath = FileUtil.toSystemIndependentName(file.getParent());
+ String classpath = moduleRoot.getAttributeValue(CLASSPATH_ATTRIBUTE);
+ if (classpath == null) {
+ JpsModuleRootModelSerializer.loadRootModel(module, JDomSerializationUtil.findComponent(moduleRoot, "NewModuleRootManager"),
+ projectSdkType);
+ }
+ else {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ JpsModuleClasspathSerializer classpathSerializer = extension.getClasspathSerializer();
+ if (classpathSerializer != null && classpathSerializer.getClasspathId().equals(classpath)) {
+ String classpathDir = moduleRoot.getAttributeValue(CLASSPATH_DIR_ATTRIBUTE);
+ classpathSerializer.loadClasspath(module, classpathDir, baseModulePath, expander, paths, projectSdkType);
+ }
+ }
+ }
+ JpsFacetSerializer.loadFacets(module, JDomSerializationUtil.findComponent(moduleRoot, "FacetManager"));
+ return module;
+ }
+
+ static JpsMacroExpander createModuleMacroExpander(final Map<String, String> pathVariables, File moduleFile) {
+ final JpsMacroExpander expander = new JpsMacroExpander(pathVariables);
+ String moduleDirPath = PathMacroUtil.getModuleDir(moduleFile.getAbsolutePath());
+ if (moduleDirPath != null) {
+ expander.addFileHierarchyReplacements(PathMacroUtil.MODULE_DIR_MACRO_NAME, new File(FileUtil.toSystemDependentName(moduleDirPath)));
+ }
+ return expander;
+ }
+
+ private static <P extends JpsElement> JpsModule createModule(String name, Element moduleRoot, JpsModulePropertiesSerializer<P> loader) {
+ String componentName = loader.getComponentName();
+ Element component = componentName != null ? JDomSerializationUtil.findComponent(moduleRoot, componentName) : null;
+ return JpsElementFactory.getInstance().createModule(name, loader.getType(), loader.loadProperties(component));
+ }
+
+ private static JpsModulePropertiesSerializer<?> getModulePropertiesSerializer(@Nullable String typeId) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsModulePropertiesSerializer<?> loader : extension.getModulePropertiesSerializers()) {
+ if (loader.getTypeId().equals(typeId)) {
+ return loader;
+ }
+ }
+ }
+ return new JpsModulePropertiesSerializer<JpsDummyElement>(JpsJavaModuleType.INSTANCE, "JAVA_MODULE", null) {
+ @Override
+ public JpsDummyElement loadProperties(@Nullable Element componentElement) {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+
+ @Override
+ public void saveProperties(@NotNull JpsDummyElement properties, @NotNull Element componentElement) {
+ }
+ };
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectSerializationDataExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectSerializationDataExtension.java
new file mode 100644
index 000000000000..ff6e6ae9decf
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectSerializationDataExtension.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface JpsProjectSerializationDataExtension extends JpsElement {
+ @NotNull
+ File getBaseDirectory();
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
new file mode 100644
index 000000000000..be0e60712f53
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class PathMacroUtil {
+ @NonNls public static final String PROJECT_DIR_MACRO_NAME = "PROJECT_DIR";
+ @NonNls public static final String MODULE_DIR_MACRO_NAME = "MODULE_DIR";
+ @NonNls public static final String DIRECTORY_STORE_NAME = ".idea";
+ @NonNls public static final String APPLICATION_HOME_DIR = "APPLICATION_HOME_DIR";
+
+ @Nullable
+ public static String getModuleDir(String moduleFilePath) {
+ File moduleDirFile = new File(moduleFilePath).getParentFile();
+ if (moduleDirFile == null) return null;
+
+ // hack so that, if a module is stored inside the .idea directory, the base directory
+ // rather than the .idea directory itself is considered the module root
+ // (so that a Ruby IDE project doesn't break if its directory is moved together with the .idea directory)
+ File moduleDirParent = moduleDirFile.getParentFile();
+ if (moduleDirParent != null && moduleDirFile.getName().equals(DIRECTORY_STORE_NAME)) {
+ moduleDirFile = moduleDirParent;
+ }
+ String moduleDir = moduleDirFile.getPath();
+ moduleDir = moduleDir.replace(File.separatorChar, '/');
+ if (moduleDir.endsWith(":/")) {
+ moduleDir = moduleDir.substring(0, moduleDir.length() - 1);
+ }
+ return moduleDir;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java
new file mode 100644
index 000000000000..0fb3cee44718
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Tag;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+@Tag("artifacts")
+public class ArtifactManagerState {
+ private List<ArtifactState> myArtifacts = new ArrayList<ArtifactState>();
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public List<ArtifactState> getArtifacts() {
+ return myArtifacts;
+ }
+
+ public void setArtifacts(List<ArtifactState> artifacts) {
+ myArtifacts = artifacts;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java
new file mode 100644
index 000000000000..61ca07389b29
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jdom.Element;
+
+/**
+ * @author nik
+ */
+@Tag("properties")
+public class ArtifactPropertiesState {
+ private String myId;
+ private Element myOptions;
+
+ @Attribute("id")
+ public String getId() {
+ return myId;
+ }
+
+ @Tag("options")
+ public Element getOptions() {
+ return myOptions;
+ }
+
+ public void setId(String id) {
+ myId = id;
+ }
+
+ public void setOptions(Element options) {
+ myOptions = options;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java
new file mode 100644
index 000000000000..eaa38bb2195f
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author nik
+ */
+@Tag("artifact")
+public class ArtifactState {
+ @NonNls public static final String NAME_ATTRIBUTE = "name";
+ private String myName;
+ private String myOutputPath;
+ private String myArtifactType = "plain";
+ private boolean myBuildOnMake;
+ private Element myRootElement;
+ private List<ArtifactPropertiesState> myPropertiesList = new ArrayList<ArtifactPropertiesState>();
+
+ @Attribute(NAME_ATTRIBUTE)
+ public String getName() {
+ return myName;
+ }
+
+ @Attribute("type")
+ public String getArtifactType() {
+ return myArtifactType;
+ }
+
+ @Attribute("build-on-make")
+ public boolean isBuildOnMake() {
+ return myBuildOnMake;
+ }
+
+ @Tag("output-path")
+ public String getOutputPath() {
+ return myOutputPath;
+ }
+
+ @Tag("root")
+ public Element getRootElement() {
+ return myRootElement;
+ }
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public List<ArtifactPropertiesState> getPropertiesList() {
+ return myPropertiesList;
+ }
+
+ public void setPropertiesList(List<ArtifactPropertiesState> propertiesList) {
+ myPropertiesList = propertiesList;
+ }
+
+ public void setArtifactType(String artifactType) {
+ myArtifactType = artifactType;
+ }
+
+ public void setName(String name) {
+ myName = name;
+ }
+
+ public void setOutputPath(String outputPath) {
+ myOutputPath = outputPath;
+ }
+
+ public void setBuildOnMake(boolean buildOnMake) {
+ myBuildOnMake = buildOnMake;
+ }
+
+ public void setRootElement(Element rootElement) {
+ myRootElement = rootElement;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactDummyPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactDummyPropertiesSerializer.java
new file mode 100644
index 000000000000..829bbdffb9cd
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactDummyPropertiesSerializer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactDummyPropertiesSerializer extends JpsArtifactPropertiesSerializer<JpsDummyElement> {
+ public JpsArtifactDummyPropertiesSerializer(String typeId, JpsArtifactType<JpsDummyElement> type) {
+ super(typeId, type);
+ }
+
+ @Override
+ public JpsDummyElement loadProperties(List<ArtifactPropertiesState> stateList) {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+
+ @Override
+ public void saveProperties(JpsDummyElement properties, List<ArtifactPropertiesState> stateList) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactExtensionSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactExtensionSerializer.java
new file mode 100644
index 000000000000..a911504ec52f
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactExtensionSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+
+/**
+ * @author nik
+ */
+public abstract class JpsArtifactExtensionSerializer<E extends JpsElement> {
+ private JpsElementChildRole<E> myRole;
+ private String myId;
+
+ protected JpsArtifactExtensionSerializer(String id, JpsElementChildRole<E> role) {
+ myId = id;
+ myRole = role;
+ }
+
+ public JpsElementChildRole<E> getRole() {
+ return myRole;
+ }
+
+ public String getId() {
+ return myId;
+ }
+
+ public abstract E loadExtension(@Nullable Element optionsTag);
+
+ public abstract void saveExtension(@NotNull E extension, @NotNull Element optionsTag);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactPropertiesSerializer.java
new file mode 100644
index 000000000000..bff5d3be2993
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactPropertiesSerializer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+import org.jetbrains.jps.model.serialization.JpsElementPropertiesSerializer;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsArtifactPropertiesSerializer<P extends JpsElement> extends JpsElementPropertiesSerializer<P, JpsArtifactType<P>> {
+ public JpsArtifactPropertiesSerializer(String typeId, JpsArtifactType<P> type) {
+ super(type, typeId);
+ }
+
+ public abstract P loadProperties(List<ArtifactPropertiesState> stateList);
+
+ public abstract void saveProperties(P properties, List<ArtifactPropertiesState> stateList);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactSerializer.java
new file mode 100644
index 000000000000..d689514ad21e
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactSerializer.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.artifact.*;
+import org.jetbrains.jps.model.artifact.elements.*;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactSerializer {
+ private static JpsPackagingElementSerializer<?>[] STANDARD_SERIALIZERS = {
+ new ArtifactRootElementSerializer(),
+ new DirectoryElementSerializer(),
+ new ArchiveElementSerializer(),
+ new FileCopyElementSerializer(),
+ new DirectoryCopyElementSerializer(),
+ new ExtractedDirectoryElementSerializer(),
+ new LibraryFilesElementSerializer(),
+ new ArtifactOutputElementSerializer()
+ };
+ private static final JpsArtifactPropertiesSerializer<?>[] STANDARD_TYPE_SERIALIZERS = {
+ new JpsArtifactDummyPropertiesSerializer("plain", DirectoryArtifactType.INSTANCE),
+ new JpsArtifactDummyPropertiesSerializer("jar", JarArtifactType.INSTANCE)
+ };
+ private static final String ELEMENT_TAG = "element";
+ private static final String ID_ATTRIBUTE = "id";
+ private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
+
+
+ public static void loadArtifacts(@NotNull JpsProject project, @Nullable Element componentElement) {
+ JpsArtifactService service = JpsArtifactService.getInstance();
+ for (Element artifactElement : JDOMUtil.getChildren(componentElement, "artifact")) {
+ ArtifactState state = XmlSerializer.deserialize(artifactElement, ArtifactState.class);
+ if (state == null) continue;
+ JpsArtifactPropertiesSerializer<?> serializer = getTypePropertiesSerializer(state.getArtifactType());
+ loadArtifact(project, service, state, serializer);
+ }
+ }
+
+ private static <P extends JpsElement> void loadArtifact(JpsProject project, JpsArtifactService service, ArtifactState state, JpsArtifactPropertiesSerializer<P> serializer) {
+ JpsPackagingElement rootElement = loadPackagingElement(state.getRootElement());
+ if (rootElement != null) {
+ List<ArtifactPropertiesState> propertiesList = state.getPropertiesList();
+ JpsArtifact artifact = service.addArtifact(project, state.getName(), (JpsCompositePackagingElement)rootElement,
+ serializer.getType(), serializer.loadProperties(propertiesList));
+ artifact.setBuildOnMake(state.isBuildOnMake());
+ artifact.setOutputPath(state.getOutputPath());
+ for (ArtifactPropertiesState propertiesState : propertiesList) {
+ JpsArtifactExtensionSerializer<?> extensionSerializer = getExtensionSerializer(propertiesState.getId());
+ if (extensionSerializer != null) {
+ loadExtension(extensionSerializer, artifact, propertiesState.getOptions());
+ }
+ }
+ }
+ }
+
+ public static void saveArtifact(@NotNull JpsArtifact artifact, Element componentElement) {
+ ArtifactState state = new ArtifactState();
+ state.setName(artifact.getName());
+ state.setBuildOnMake(artifact.isBuildOnMake());
+ state.setOutputPath(artifact.getOutputPath());
+ JpsArtifactPropertiesSerializer<?> serializer = getTypePropertiesSerializer(artifact.getArtifactType());
+ doSaveArtifact(artifact, componentElement, state, serializer);
+ }
+
+ private static <P extends JpsElement> void doSaveArtifact(JpsArtifact artifact, Element componentElement, ArtifactState state,
+ JpsArtifactPropertiesSerializer<P> serializer) {
+ state.setArtifactType(serializer.getTypeId());
+ state.setRootElement(savePackagingElement(artifact.getRootElement()));
+ List<ArtifactPropertiesState> propertiesList = state.getPropertiesList();
+ //noinspection unchecked
+ serializer.saveProperties((P)artifact.getProperties(), propertiesList);
+ for (JpsModelSerializerExtension serializerExtension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsArtifactExtensionSerializer<?> extensionSerializer : serializerExtension.getArtifactExtensionSerializers()) {
+ JpsElement extension = artifact.getContainer().getChild(extensionSerializer.getRole());
+ if (extension != null) {
+ ArtifactPropertiesState propertiesState = new ArtifactPropertiesState();
+ propertiesState.setId(extensionSerializer.getId());
+ propertiesState.setOptions(saveExtension(extensionSerializer, extension));
+ propertiesList.add(propertiesState);
+ }
+ }
+ }
+ componentElement.addContent(XmlSerializer.serialize(state, SERIALIZATION_FILTERS));
+ }
+
+ private static <E extends JpsElement> void loadExtension(JpsArtifactExtensionSerializer<E> serializer,
+ JpsArtifact artifact,
+ Element options) {
+ E e = serializer.loadExtension(options);
+ artifact.getContainer().setChild(serializer.getRole(), e);
+ }
+
+ private static <E extends JpsElement> Element saveExtension(JpsArtifactExtensionSerializer<?> serializer,
+ E extension) {
+ Element optionsTag = new Element("options");
+ //noinspection unchecked
+ ((JpsArtifactExtensionSerializer<E>)serializer).saveExtension(extension, optionsTag);
+ return optionsTag;
+ }
+
+ private static <P extends JpsPackagingElement> Element savePackagingElement(P element) {
+ //noinspection unchecked
+ JpsPackagingElementSerializer<P> serializer = findElementSerializer((Class<P>)element.getClass());
+ Element tag = new Element(ELEMENT_TAG).setAttribute(ID_ATTRIBUTE, serializer.getTypeId());
+ serializer.save(element, tag);
+ if (element instanceof JpsCompositePackagingElement) {
+ for (JpsPackagingElement child : ((JpsCompositePackagingElement)element).getChildren()) {
+ tag.addContent(savePackagingElement(child));
+ }
+ }
+ return tag;
+ }
+
+ @Nullable
+ private static JpsPackagingElement loadPackagingElement(Element element) {
+ JpsPackagingElement packagingElement = createPackagingElement(element);
+ if (packagingElement instanceof JpsCompositePackagingElement) {
+ for (Element childElement : JDOMUtil.getChildren(element, ELEMENT_TAG)) {
+ JpsPackagingElement child = loadPackagingElement(childElement);
+ if (child != null) {
+ ((JpsCompositePackagingElement)packagingElement).addChild(child);
+ }
+ }
+ }
+ return packagingElement;
+ }
+
+ @Nullable
+ private static JpsPackagingElement createPackagingElement(Element element) {
+ String typeId = element.getAttributeValue(ID_ATTRIBUTE);
+ JpsPackagingElementSerializer<?> serializer = findElementSerializer(typeId);
+ if (serializer != null) {
+ return serializer.load(element);
+ }
+ return null;
+ }
+
+ @Nullable
+ private static JpsPackagingElementSerializer<?> findElementSerializer(@NotNull String typeId) {
+ for (JpsPackagingElementSerializer<?> serializer : STANDARD_SERIALIZERS) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsPackagingElementSerializer<?> serializer : extension.getPackagingElementSerializers()) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ private static <E extends JpsPackagingElement> JpsPackagingElementSerializer<E> findElementSerializer(@NotNull Class<E> elementClass) {
+ for (JpsPackagingElementSerializer<?> serializer : STANDARD_SERIALIZERS) {
+ if (serializer.getElementClass().isAssignableFrom(elementClass)) {
+ //noinspection unchecked
+ return (JpsPackagingElementSerializer<E>)serializer;
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsPackagingElementSerializer<?> serializer : extension.getPackagingElementSerializers()) {
+ if (serializer.getElementClass().isAssignableFrom(elementClass)) {
+ //noinspection unchecked
+ return (JpsPackagingElementSerializer<E>)serializer;
+ }
+ }
+ }
+ throw new IllegalArgumentException("Serializer not found for " + elementClass);
+ }
+
+ @Nullable
+ private static JpsArtifactExtensionSerializer<?> getExtensionSerializer(String id) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsArtifactExtensionSerializer<?> serializer : extension.getArtifactExtensionSerializers()) {
+ if (serializer.getId().equals(id)) {
+ return serializer;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static JpsArtifactPropertiesSerializer<?> getTypePropertiesSerializer(String typeId) {
+ for (JpsArtifactPropertiesSerializer serializer : STANDARD_TYPE_SERIALIZERS) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsArtifactPropertiesSerializer serializer : extension.getArtifactTypePropertiesSerializers()) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ }
+ return STANDARD_TYPE_SERIALIZERS[0];
+ }
+
+ private static JpsArtifactPropertiesSerializer<?> getTypePropertiesSerializer(JpsArtifactType type) {
+ for (JpsArtifactPropertiesSerializer serializer : STANDARD_TYPE_SERIALIZERS) {
+ if (serializer.getType().equals(type)) {
+ return serializer;
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsArtifactPropertiesSerializer serializer : extension.getArtifactTypePropertiesSerializers()) {
+ if (serializer.getType().equals(type)) {
+ return serializer;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static class ArtifactRootElementSerializer extends JpsPackagingElementSerializer<JpsArtifactRootElement> {
+ public ArtifactRootElementSerializer() {
+ super("root", JpsArtifactRootElement.class);
+ }
+
+ @Override
+ public JpsArtifactRootElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createArtifactRoot();
+ }
+
+ @Override
+ public void save(JpsArtifactRootElement element, Element tag) {
+ }
+ }
+
+ private static class DirectoryElementSerializer extends JpsPackagingElementSerializer<JpsDirectoryPackagingElement> {
+ public DirectoryElementSerializer() {
+ super("directory", JpsDirectoryPackagingElement.class);
+ }
+
+ @Override
+ public JpsDirectoryPackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createDirectory(element.getAttributeValue("name"));
+ }
+
+ @Override
+ public void save(JpsDirectoryPackagingElement element, Element tag) {
+ tag.setAttribute("name", element.getDirectoryName());
+ }
+ }
+
+ private static class ArchiveElementSerializer extends JpsPackagingElementSerializer<JpsArchivePackagingElement> {
+ public ArchiveElementSerializer() {
+ super("archive", JpsArchivePackagingElement.class);
+ }
+
+ @Override
+ public JpsArchivePackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createArchive(element.getAttributeValue("name"));
+ }
+
+ @Override
+ public void save(JpsArchivePackagingElement element, Element tag) {
+ tag.setAttribute("name", element.getArchiveName());
+ }
+ }
+
+ private static class FileCopyElementSerializer extends JpsPackagingElementSerializer<JpsFileCopyPackagingElement> {
+ public FileCopyElementSerializer() {
+ super("file-copy", JpsFileCopyPackagingElement.class);
+ }
+
+ @Override
+ public JpsFileCopyPackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createFileCopy(element.getAttributeValue("path"),
+ element.getAttributeValue("output-file-name"));
+ }
+
+ @Override
+ public void save(JpsFileCopyPackagingElement element, Element tag) {
+ tag.setAttribute("path", element.getFilePath());
+ String outputFileName = element.getRenamedOutputFileName();
+ if (outputFileName != null) {
+ tag.setAttribute("output-path-name", outputFileName);
+ }
+ }
+ }
+
+ private static class DirectoryCopyElementSerializer extends JpsPackagingElementSerializer<JpsDirectoryCopyPackagingElement> {
+ public DirectoryCopyElementSerializer() {
+ super("dir-copy", JpsDirectoryCopyPackagingElement.class);
+ }
+
+ @Override
+ public JpsDirectoryCopyPackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createDirectoryCopy(element.getAttributeValue("path"));
+ }
+
+ @Override
+ public void save(JpsDirectoryCopyPackagingElement element, Element tag) {
+ tag.setAttribute("path", element.getDirectoryPath());
+ }
+ }
+
+ private static class ExtractedDirectoryElementSerializer
+ extends JpsPackagingElementSerializer<JpsExtractedDirectoryPackagingElement> {
+ public ExtractedDirectoryElementSerializer() {
+ super("extracted-dir", JpsExtractedDirectoryPackagingElement.class);
+ }
+
+ @Override
+ public JpsExtractedDirectoryPackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance().createExtractedDirectory(element.getAttributeValue("path"),
+ element.getAttributeValue("path-in-jar"));
+ }
+
+ @Override
+ public void save(JpsExtractedDirectoryPackagingElement element, Element tag) {
+ tag.setAttribute("path", element.getFilePath());
+ tag.setAttribute("path-in-jar", element.getPathInJar());
+ }
+ }
+
+ private static class LibraryFilesElementSerializer extends JpsPackagingElementSerializer<JpsLibraryFilesPackagingElement> {
+ public LibraryFilesElementSerializer() {
+ super("library", JpsLibraryFilesPackagingElement.class);
+ }
+
+ @Override
+ public JpsLibraryFilesPackagingElement load(Element element) {
+ String level = element.getAttributeValue("level");
+ String libraryName = element.getAttributeValue("name");
+ String moduleName = element.getAttributeValue("module-name");
+ JpsElementReference<? extends JpsCompositeElement> parentReference;
+ if (moduleName != null) {
+ parentReference = JpsElementFactory.getInstance().createModuleReference(moduleName);
+ }
+ else {
+ parentReference = JpsLibraryTableSerializer.createLibraryTableReference(level);
+ }
+ return JpsPackagingElementFactory.getInstance()
+ .createLibraryElement(JpsElementFactory.getInstance().createLibraryReference(libraryName, parentReference));
+ }
+
+ @Override
+ public void save(JpsLibraryFilesPackagingElement element, Element tag) {
+ JpsLibraryReference reference = element.getLibraryReference();
+ JpsElementReference<? extends JpsCompositeElement> parentReference = reference.getParentReference();
+ tag.setAttribute("level", JpsLibraryTableSerializer.getLevelId(parentReference));
+ tag.setAttribute("name", reference.getLibraryName());
+ if (parentReference instanceof JpsModuleReference) {
+ tag.setAttribute("module-name", ((JpsModuleReference)parentReference).getModuleName());
+ }
+ }
+ }
+
+ private static class ArtifactOutputElementSerializer extends JpsPackagingElementSerializer<JpsArtifactOutputPackagingElement> {
+ public ArtifactOutputElementSerializer() {
+ super("artifact", JpsArtifactOutputPackagingElement.class);
+ }
+
+ @Override
+ public JpsArtifactOutputPackagingElement load(Element element) {
+ return JpsPackagingElementFactory.getInstance()
+ .createArtifactOutput(JpsArtifactService.getInstance().createReference(element.getAttributeValue("artifact-name")));
+ }
+
+ @Override
+ public void save(JpsArtifactOutputPackagingElement element, Element tag) {
+ tag.setAttribute("artifact-name", element.getArtifactReference().getArtifactName());
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementSerializer.java
new file mode 100644
index 000000000000..5cc33aafcdd7
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementSerializer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.artifact;
+
+import org.jdom.Element;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+
+/**
+ * @author nik
+ */
+public abstract class JpsPackagingElementSerializer<E extends JpsPackagingElement> {
+ private final String myTypeId;
+ private final Class<? extends E> myElementClass;
+
+ protected JpsPackagingElementSerializer(String typeId, Class<? extends E> elementClass) {
+ myTypeId = typeId;
+ myElementClass = elementClass;
+ }
+
+ public String getTypeId() {
+ return myTypeId;
+ }
+
+ public Class<? extends E> getElementClass() {
+ return myElementClass;
+ }
+
+ public abstract E load(Element element);
+
+ public abstract void save(E element, Element tag);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetManagerState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetManagerState.java
new file mode 100644
index 000000000000..586417464092
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetManagerState.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.model.serialization.facet;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author nik
+*/
+public class FacetManagerState {
+ private List<FacetState> myFacets = new ArrayList<FacetState>();
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public List<FacetState> getFacets() {
+ return myFacets;
+ }
+
+ public void setFacets(final List<FacetState> facets) {
+ myFacets = facets;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetState.java
new file mode 100644
index 000000000000..fb528d73ef8f
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/FacetState.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jps.model.serialization.facet;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+import org.jdom.Element;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author nik
+*/
+@Tag(JpsFacetSerializer.FACET_TAG)
+public class FacetState {
+ private String myFacetType;
+ private String myName;
+ private Element myConfiguration;
+ private List<FacetState> mySubFacets = new ArrayList<FacetState>();
+
+ @Attribute(JpsFacetSerializer.TYPE_ATTRIBUTE)
+ public String getFacetType() {
+ return myFacetType;
+ }
+
+ @Attribute(JpsFacetSerializer.NAME_ATTRIBUTE)
+ public String getName() {
+ return myName;
+ }
+
+ @Tag(JpsFacetSerializer.CONFIGURATION_TAG)
+ public Element getConfiguration() {
+ return myConfiguration;
+ }
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public List<FacetState> getSubFacets() {
+ return mySubFacets;
+ }
+
+ public void setSubFacets(final List<FacetState> subFacets) {
+ mySubFacets = subFacets;
+ }
+
+ public void setConfiguration(final Element configuration) {
+ myConfiguration = configuration;
+ }
+
+ public void setName(final String name) {
+ myName = name;
+ }
+
+ public void setFacetType(final String type) {
+ myFacetType = type;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetConfigurationSerializer.java
new file mode 100644
index 000000000000..3f3a482d295c
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetConfigurationSerializer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.facet;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsFacetConfigurationSerializer<E extends JpsElement> {
+ private final JpsElementChildRole<E> myRole;
+ private final String myFacetTypeId;
+ private final String myFacetName;
+
+ public JpsFacetConfigurationSerializer(JpsElementChildRole<E> role, String facetTypeId, final @Nullable String facetName) {
+ myRole = role;
+ myFacetTypeId = facetTypeId;
+ myFacetName = facetName;
+ }
+
+ public String getFacetTypeId() {
+ return myFacetTypeId;
+ }
+
+ public E loadExtension(final Element configurationElement, final String facetName, JpsModule module, JpsElement parentFacet) {
+ final E e = loadExtension(configurationElement, facetName, parentFacet, module);
+ return module.getContainer().setChild(myRole, e);
+ }
+
+ protected abstract E loadExtension(@NotNull Element facetConfigurationElement, String name, JpsElement parent, JpsModule module);
+
+ public boolean hasExtension(JpsModule module) {
+ return module.getContainer().getChild(myRole) != null;
+ }
+
+ public void saveExtension(JpsModule module, @NotNull List<FacetState> states) {
+ E extension = module.getContainer().getChild(myRole);
+ if (extension != null) {
+ FacetState state = new FacetState();
+ state.setFacetType(myFacetTypeId);
+ state.setName(myFacetName);
+ Element tag = new Element(JpsFacetSerializer.CONFIGURATION_TAG);
+ saveExtension(extension, tag, module);
+ state.setConfiguration(tag);
+ states.add(state);
+ }
+ }
+
+ protected abstract void saveExtension(E extension, Element facetConfigurationTag, JpsModule module);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java
new file mode 100644
index 000000000000..6f577d97f5a9
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.facet;
+
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsFacetSerializer {
+ @NonNls public static final String FACET_TAG = "facet";
+ @NonNls public static final String TYPE_ATTRIBUTE = "type";
+ @NonNls public static final String CONFIGURATION_TAG = "configuration";
+ @NonNls public static final String NAME_ATTRIBUTE = "name";
+
+ public static void loadFacets(JpsModule module, @Nullable Element facetManagerElement) {
+ if (facetManagerElement == null) return;
+ final FacetManagerState state = XmlSerializer.deserialize(facetManagerElement, FacetManagerState.class);
+ if (state != null) {
+ addFacets(module, state.getFacets(), null);
+ }
+ }
+
+ public static void saveFacets(JpsModule module, @NotNull Element facetManagerElement) {
+ FacetManagerState managerState = new FacetManagerState();
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsFacetConfigurationSerializer<?> serializer : extension.getFacetConfigurationSerializers()) {
+ if (serializer.hasExtension(module)) {
+ serializer.saveExtension(module, managerState.getFacets());
+ }
+ }
+ }
+ XmlSerializer.serializeInto(managerState, facetManagerElement, new SkipDefaultValuesSerializationFilters());
+ }
+
+ private static void addFacets(JpsModule module, List<FacetState> facets, @Nullable final JpsElement parentFacet) {
+ for (FacetState facetState : facets) {
+ final JpsFacetConfigurationSerializer<?> serializer = getModuleExtensionSerializer(facetState.getFacetType());
+ if (serializer != null) {
+ final JpsElement element = addExtension(module, serializer, facetState, parentFacet);
+ addFacets(module, facetState.getSubFacets(), element);
+ }
+ }
+ }
+
+ private static <E extends JpsElement> E addExtension(JpsModule module, JpsFacetConfigurationSerializer<E> serializer, FacetState facet,
+ JpsElement parentFacet) {
+ return serializer.loadExtension(facet.getConfiguration(), facet.getName(), module, parentFacet);
+ }
+
+ @Nullable
+ private static JpsFacetConfigurationSerializer<?> getModuleExtensionSerializer(@NotNull String typeId) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsFacetConfigurationSerializer<?> serializer : extension.getFacetConfigurationSerializers()) {
+ if (serializer.getFacetTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static JpsModuleReference createModuleReference(String facetId) {
+ String moduleName = facetId.substring(0, facetId.indexOf('/'));
+ return JpsElementFactory.getInstance().createModuleReference(moduleName);
+ }
+
+ public static String getFacetId(final JpsModuleReference moduleReference, final String facetTypeId, final String facetName) {
+ return moduleReference.getModuleName() + "/" + facetTypeId + "/" + facetName;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsModuleSerializationDataExtensionImpl.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsModuleSerializationDataExtensionImpl.java
new file mode 100644
index 000000000000..0a8fe0a074bf
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsModuleSerializationDataExtensionImpl.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.serialization.module.JpsModuleSerializationDataExtension;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsModuleSerializationDataExtensionImpl extends JpsElementBase<JpsModuleSerializationDataExtensionImpl> implements
+ JpsModuleSerializationDataExtension {
+ public static final JpsElementChildRole<JpsModuleSerializationDataExtension> ROLE = JpsElementChildRoleBase.create("module serialization data");
+ private File myBaseDirectory;
+
+ public JpsModuleSerializationDataExtensionImpl(File baseDirectory) {
+ myBaseDirectory = baseDirectory;
+ }
+
+ @NotNull
+ @Override
+ public JpsModuleSerializationDataExtensionImpl createCopy() {
+ return new JpsModuleSerializationDataExtensionImpl(myBaseDirectory);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsModuleSerializationDataExtensionImpl modified) {
+ }
+
+ @NotNull
+ @Override
+ public File getBaseDirectory() {
+ return myBaseDirectory;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsProjectSerializationDataExtensionImpl.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsProjectSerializationDataExtensionImpl.java
new file mode 100644
index 000000000000..5de35188e78b
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/impl/JpsProjectSerializationDataExtensionImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.serialization.JpsProjectSerializationDataExtension;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsProjectSerializationDataExtensionImpl extends JpsElementBase<JpsProjectSerializationDataExtensionImpl> implements JpsProjectSerializationDataExtension {
+ public static final JpsElementChildRole<JpsProjectSerializationDataExtension> ROLE = JpsElementChildRoleBase.create("serialization data");
+ private File myBaseDirectory;
+
+ public JpsProjectSerializationDataExtensionImpl(File baseDirectory) {
+ myBaseDirectory = baseDirectory;
+ }
+
+ @NotNull
+ @Override
+ public JpsProjectSerializationDataExtensionImpl createCopy() {
+ return new JpsProjectSerializationDataExtensionImpl(myBaseDirectory);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsProjectSerializationDataExtensionImpl modified) {
+ }
+
+ @NotNull
+ @Override
+ public File getBaseDirectory() {
+ return myBaseDirectory;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsApplicationRunConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsApplicationRunConfigurationSerializer.java
new file mode 100644
index 000000000000..2a6ed823ba58
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsApplicationRunConfigurationSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationProperties;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationState;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationType;
+import org.jetbrains.jps.model.serialization.runConfigurations.JpsRunConfigurationPropertiesSerializer;
+
+/**
+ * Currently java run configurations aren't used in external compiler so this serializer is registered for tests only for performance reasons
+ *
+ * @author nik
+ */
+public class JpsApplicationRunConfigurationSerializer extends JpsRunConfigurationPropertiesSerializer<JpsApplicationRunConfigurationProperties> {
+ public JpsApplicationRunConfigurationSerializer() {
+ super(JpsApplicationRunConfigurationType.INSTANCE, "Application");
+ }
+
+ @Override
+ public JpsApplicationRunConfigurationProperties loadProperties(@Nullable Element runConfigurationTag) {
+ JpsApplicationRunConfigurationState properties = runConfigurationTag != null ?
+ XmlSerializer.deserialize(runConfigurationTag, JpsApplicationRunConfigurationState.class) : new JpsApplicationRunConfigurationState();
+ return JpsJavaExtensionService.getInstance().createRunConfigurationProperties(properties != null ? properties : new JpsApplicationRunConfigurationState());
+ }
+
+ @Override
+ public void saveProperties(JpsApplicationRunConfigurationProperties properties, Element runConfigurationTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java
new file mode 100644
index 000000000000..90bfa354af09
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.JpsUrlList;
+import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+import org.jetbrains.jps.model.serialization.artifact.JpsPackagingElementSerializer;
+import org.jetbrains.jps.model.serialization.java.compiler.*;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryRootTypeSerializer;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension {
+ public static final String EXPORTED_ATTRIBUTE = "exported";
+ public static final String SCOPE_ATTRIBUTE = "scope";
+ public static final String OUTPUT_TAG = "output";
+ public static final String URL_ATTRIBUTE = "url";
+ public static final String LANGUAGE_LEVEL_ATTRIBUTE = "languageLevel";
+ public static final String EXPLODED_TAG = "exploded";
+ public static final String EXCLUDE_EXPLODED_TAG = "exclude-exploded";
+ public static final String TEST_OUTPUT_TAG = "output-test";
+ public static final String INHERIT_COMPILER_OUTPUT_ATTRIBUTE = "inherit-compiler-output";
+ public static final String EXCLUDE_OUTPUT_TAG = "exclude-output";
+ private static final String ANNOTATION_PATHS_TAG = "annotation-paths";
+ private static final String JAVADOC_PATHS_TAG = "javadoc-paths";
+ private static final String MODULE_LANGUAGE_LEVEL_ATTRIBUTE = "LANGUAGE_LEVEL";
+ public static final String ROOT_TAG = "root";
+
+ @Override
+ public void loadRootModel(@NotNull JpsModule module, @NotNull Element rootModel) {
+ loadExplodedDirectoryExtension(module, rootModel);
+ loadJavaModuleExtension(module, rootModel);
+ }
+
+ @Override
+ public void saveRootModel(@NotNull JpsModule module, @NotNull Element rootModel) {
+ saveExplodedDirectoryExtension(module, rootModel);
+ saveJavaModuleExtension(module, rootModel);
+ }
+
+ @NotNull
+ @Override
+ public List<? extends JpsProjectExtensionSerializer> getProjectExtensionSerializers() {
+ return Arrays.asList(new JavaProjectExtensionSerializer(),
+ new JpsJavaCompilerConfigurationSerializer(),
+ new JpsJavaCompilerWorkspaceConfigurationSerializer(),
+ new JpsJavaCompilerOptionsSerializer("JavacSettings", "Javac"),
+ new JpsEclipseCompilerOptionsSerializer("EclipseCompilerSettings", "Eclipse"),
+ new RmicCompilerOptionsSerializer("RmicSettings", "Rmic"));
+ }
+
+ @Override
+ public void loadModuleDependencyProperties(JpsDependencyElement dependency, Element entry) {
+ boolean exported = entry.getAttributeValue(EXPORTED_ATTRIBUTE) != null;
+ String scopeName = entry.getAttributeValue(SCOPE_ATTRIBUTE);
+ JpsJavaDependencyScope scope = scopeName != null ? JpsJavaDependencyScope.valueOf(scopeName) : JpsJavaDependencyScope.COMPILE;
+
+ final JpsJavaDependencyExtension extension = getService().getOrCreateDependencyExtension(dependency);
+ extension.setExported(exported);
+ extension.setScope(scope);
+ }
+
+ @Override
+ public void saveModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ JpsJavaDependencyExtension extension = getService().getDependencyExtension(dependency);
+ if (extension != null) {
+ if (extension.isExported()) {
+ orderEntry.setAttribute(EXPORTED_ATTRIBUTE, "");
+ }
+ JpsJavaDependencyScope scope = extension.getScope();
+ if (scope != JpsJavaDependencyScope.COMPILE) {
+ orderEntry.setAttribute(SCOPE_ATTRIBUTE, scope.name());
+ }
+ }
+ }
+
+ @Override
+ public List<JpsLibraryRootTypeSerializer> getLibraryRootTypeSerializers() {
+ return Arrays.asList(new JpsLibraryRootTypeSerializer("JAVADOC", JpsOrderRootType.DOCUMENTATION, true),
+ new JpsLibraryRootTypeSerializer("ANNOTATIONS", JpsAnnotationRootType.INSTANCE, false));
+ }
+
+ @NotNull
+ @Override
+ public List<JpsLibraryRootTypeSerializer> getSdkRootTypeSerializers() {
+ return Arrays.asList(new JpsLibraryRootTypeSerializer("javadocPath", JpsOrderRootType.DOCUMENTATION, true),
+ new JpsLibraryRootTypeSerializer("annotationsPath", JpsAnnotationRootType.INSTANCE, true));
+ }
+
+ @Override
+ public List<? extends JpsPackagingElementSerializer<?>> getPackagingElementSerializers() {
+ return Arrays.asList(new JpsModuleOutputPackagingElementSerializer(), new JpsTestModuleOutputPackagingElementSerializer());
+ }
+
+ private static void loadExplodedDirectoryExtension(JpsModule module, Element rootModelComponent) {
+ final Element exploded = rootModelComponent.getChild(EXPLODED_TAG);
+ if (exploded != null) {
+ final ExplodedDirectoryModuleExtension extension = getService().getOrCreateExplodedDirectoryExtension(module);
+ extension.setExcludeExploded(rootModelComponent.getChild(EXCLUDE_EXPLODED_TAG) != null);
+ extension.setExplodedUrl(exploded.getAttributeValue(URL_ATTRIBUTE));
+ }
+ }
+
+ private static void saveExplodedDirectoryExtension(JpsModule module, Element rootModelElement) {
+ ExplodedDirectoryModuleExtension extension = getService().getExplodedDirectoryExtension(module);
+ if (extension != null) {
+ if (extension.isExcludeExploded()) {
+ rootModelElement.addContent(0, new Element(EXCLUDE_EXPLODED_TAG));
+ }
+ rootModelElement.addContent(0, new Element(EXPLODED_TAG).setAttribute(URL_ATTRIBUTE, extension.getExplodedUrl()));
+ }
+ }
+
+ private static void loadJavaModuleExtension(JpsModule module, Element rootModelComponent) {
+ final JpsJavaModuleExtension extension = getService().getOrCreateModuleExtension(module);
+ final Element outputTag = rootModelComponent.getChild(OUTPUT_TAG);
+ String outputUrl = outputTag != null ? outputTag.getAttributeValue(URL_ATTRIBUTE) : null;
+ extension.setOutputUrl(outputUrl);
+ final Element testOutputTag = rootModelComponent.getChild(TEST_OUTPUT_TAG);
+ String testOutputUrl = testOutputTag != null ? testOutputTag.getAttributeValue(URL_ATTRIBUTE) : null;
+ extension.setTestOutputUrl(StringUtil.isEmpty(testOutputUrl) ? outputUrl : testOutputUrl);
+
+ extension.setInheritOutput(Boolean.parseBoolean(rootModelComponent.getAttributeValue(INHERIT_COMPILER_OUTPUT_ATTRIBUTE)));
+ extension.setExcludeOutput(rootModelComponent.getChild(EXCLUDE_OUTPUT_TAG) != null);
+
+ final String languageLevel = rootModelComponent.getAttributeValue(MODULE_LANGUAGE_LEVEL_ATTRIBUTE);
+ if (languageLevel != null) {
+ extension.setLanguageLevel(LanguageLevel.valueOf(languageLevel));
+ }
+
+ loadAdditionalRoots(rootModelComponent, ANNOTATION_PATHS_TAG, extension.getAnnotationRoots());
+ loadAdditionalRoots(rootModelComponent, JAVADOC_PATHS_TAG, extension.getJavadocRoots());
+ }
+
+ private static void saveJavaModuleExtension(JpsModule module, Element rootModelComponent) {
+ JpsJavaModuleExtension extension = getService().getModuleExtension(module);
+ if (extension == null) return;
+ if (extension.isExcludeOutput()) {
+ rootModelComponent.addContent(0, new Element(EXCLUDE_OUTPUT_TAG));
+ }
+
+ String testOutputUrl = extension.getTestOutputUrl();
+ if (testOutputUrl != null) {
+ rootModelComponent.addContent(0, new Element(TEST_OUTPUT_TAG).setAttribute(URL_ATTRIBUTE, testOutputUrl));
+ }
+
+ String outputUrl = extension.getOutputUrl();
+ if (outputUrl != null) {
+ rootModelComponent.addContent(0, new Element(OUTPUT_TAG).setAttribute(URL_ATTRIBUTE, outputUrl));
+ }
+
+ LanguageLevel languageLevel = extension.getLanguageLevel();
+ if (languageLevel != null) {
+ rootModelComponent.setAttribute(MODULE_LANGUAGE_LEVEL_ATTRIBUTE, languageLevel.name());
+ }
+ rootModelComponent.setAttribute(INHERIT_COMPILER_OUTPUT_ATTRIBUTE, String.valueOf(extension.isInheritOutput()));
+ saveAdditionalRoots(rootModelComponent, JAVADOC_PATHS_TAG, extension.getJavadocRoots());
+ saveAdditionalRoots(rootModelComponent, ANNOTATION_PATHS_TAG, extension.getAnnotationRoots());
+ }
+
+ private static void loadAdditionalRoots(Element rootModelComponent, final String rootsTagName, final JpsUrlList result) {
+ final Element roots = rootModelComponent.getChild(rootsTagName);
+ for (Element root : JDOMUtil.getChildren(roots, ROOT_TAG)) {
+ result.addUrl(root.getAttributeValue(URL_ATTRIBUTE));
+ }
+ }
+
+ private static void saveAdditionalRoots(Element rootModelComponent, final String rootsTagName, final JpsUrlList list) {
+ List<String> urls = list.getUrls();
+ if (!urls.isEmpty()) {
+ Element roots = new Element(rootsTagName);
+ for (String url : urls) {
+ roots.addContent(new Element(ROOT_TAG).setAttribute(URL_ATTRIBUTE, url));
+ }
+ rootModelComponent.addContent(roots);
+ }
+ }
+
+ private static JpsJavaExtensionService getService() {
+ return JpsJavaExtensionService.getInstance();
+ }
+
+ private static class JpsModuleOutputPackagingElementSerializer
+ extends JpsPackagingElementSerializer<JpsProductionModuleOutputPackagingElement> {
+ private JpsModuleOutputPackagingElementSerializer() {
+ super("module-output", JpsProductionModuleOutputPackagingElement.class);
+ }
+
+ @Override
+ public JpsProductionModuleOutputPackagingElement load(Element element) {
+ JpsModuleReference reference = JpsElementFactory.getInstance().createModuleReference(element.getAttributeValue("name"));
+ return getService().createProductionModuleOutput(reference);
+ }
+
+ @Override
+ public void save(JpsProductionModuleOutputPackagingElement element, Element tag) {
+ tag.setAttribute("name", element.getModuleReference().getModuleName());
+ }
+ }
+
+ private static class JpsTestModuleOutputPackagingElementSerializer extends JpsPackagingElementSerializer<JpsTestModuleOutputPackagingElement> {
+ private JpsTestModuleOutputPackagingElementSerializer() {
+ super("module-test-output", JpsTestModuleOutputPackagingElement.class);
+ }
+
+ @Override
+ public JpsTestModuleOutputPackagingElement load(Element element) {
+ JpsModuleReference reference = JpsElementFactory.getInstance().createModuleReference(element.getAttributeValue("name"));
+ return getService().createTestModuleOutput(reference);
+ }
+
+ @Override
+ public void save(JpsTestModuleOutputPackagingElement element, Element tag) {
+ tag.setAttribute("name", element.getModuleReference().getModuleName());
+ }
+ }
+
+ private static class JavaProjectExtensionSerializer extends JpsProjectExtensionSerializer {
+ public JavaProjectExtensionSerializer() {
+ super(null, "ProjectRootManager");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaProjectExtension extension = getService().getOrCreateProjectExtension(project);
+ final Element output = componentTag.getChild(OUTPUT_TAG);
+ if (output != null) {
+ String url = output.getAttributeValue(URL_ATTRIBUTE);
+ if (url != null) {
+ extension.setOutputUrl(url);
+ }
+ }
+ String languageLevel = componentTag.getAttributeValue(LANGUAGE_LEVEL_ATTRIBUTE);
+ if (languageLevel != null) {
+ extension.setLanguageLevel(LanguageLevel.valueOf(languageLevel));
+ }
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaProjectExtension extension = getService().getProjectExtension(project);
+ if (extension == null) return;
+
+ String outputUrl = extension.getOutputUrl();
+ if (outputUrl != null) {
+ componentTag.addContent(new Element(OUTPUT_TAG).setAttribute(URL_ATTRIBUTE, outputUrl));
+ }
+ LanguageLevel level = extension.getLanguageLevel();
+ componentTag.setAttribute(LANGUAGE_LEVEL_ATTRIBUTE, level.name());
+ componentTag.setAttribute("assert-keyword", Boolean.toString(level.compareTo(LanguageLevel.JDK_1_4) >= 0));
+ componentTag.setAttribute("jdk-15", Boolean.toString(level.compareTo(LanguageLevel.JDK_1_5) >= 0));
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java
new file mode 100644
index 000000000000..5fcc0b41d73c
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class AnnotationProcessorProfileSerializer {
+ private static final Comparator<String> ALPHA_COMPARATOR = new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return o1.compareToIgnoreCase(o2);
+ }
+ };
+ private static final String ENTRY = "entry";
+ private static final String NAME = "name";
+ private static final String VALUE = "value";
+ private static final String ENABLED = "enabled";
+ private static final String OPTION = "option";
+ private static final String MODULE = "module";
+
+ public static void readExternal(ProcessorConfigProfile profile, Element element) {
+ profile.setName(element.getAttributeValue(NAME, ""));
+ profile.setEnabled(Boolean.valueOf(element.getAttributeValue(ENABLED, "false")));
+
+ final Element srcOutput = element.getChild("sourceOutputDir");
+ profile.setGeneratedSourcesDirectoryName(srcOutput != null ? srcOutput.getAttributeValue(NAME) : null, false);
+
+ final Element srcTestOutput = element.getChild("sourceTestOutputDir");
+ profile.setGeneratedSourcesDirectoryName(srcTestOutput != null ? srcTestOutput.getAttributeValue(NAME) : null, true);
+
+ final Element isRelativeToContentRoot = element.getChild("outputRelativeToContentRoot");
+ if (isRelativeToContentRoot != null) {
+ profile.setOutputRelativeToContentRoot(Boolean.parseBoolean(isRelativeToContentRoot.getAttributeValue(VALUE)));
+ }
+
+ profile.clearProcessorOptions();
+ for (Object optionElement : element.getChildren(OPTION)) {
+ final Element elem = (Element)optionElement;
+ final String key = elem.getAttributeValue(NAME);
+ final String value = elem.getAttributeValue(VALUE);
+ if (!StringUtil.isEmptyOrSpaces(key) && value != null) {
+ profile.setOption(key, value);
+ }
+ }
+
+ profile.clearProcessors();
+ for (Object procElement : element.getChildren("processor")) {
+ final String name = ((Element)procElement).getAttributeValue(NAME);
+ if (!StringUtil.isEmptyOrSpaces(name)) {
+ profile.addProcessor(name);
+ }
+ }
+
+ final Element pathElement = element.getChild("processorPath");
+ if (pathElement != null) {
+ profile.setObtainProcessorsFromClasspath(Boolean.parseBoolean(pathElement.getAttributeValue("useClasspath", "true")));
+ final StringBuilder pathBuilder = new StringBuilder();
+ for (Object entry : pathElement.getChildren(ENTRY)) {
+ final String path = ((Element)entry).getAttributeValue(NAME);
+ if (!StringUtil.isEmptyOrSpaces(path)) {
+ if (pathBuilder.length() > 0) {
+ pathBuilder.append(File.pathSeparator);
+ }
+ pathBuilder.append(FileUtil.toSystemDependentName(path));
+ }
+ }
+ profile.setProcessorPath(pathBuilder.toString());
+ }
+
+ profile.clearModuleNames();
+ for (Object moduleElement : element.getChildren(MODULE)) {
+ final String name = ((Element)moduleElement).getAttributeValue(NAME);
+ if (!StringUtil.isEmptyOrSpaces(name)) {
+ profile.addModuleName(name);
+ }
+ }
+ }
+
+ public static void writeExternal(ProcessorConfigProfile profile, final Element element) {
+ element.setAttribute(NAME, profile.getName());
+ element.setAttribute(ENABLED, Boolean.toString(profile.isEnabled()));
+
+ final String srcDirName = profile.getGeneratedSourcesDirectoryName(false);
+ if (!StringUtil.equals(ProcessorConfigProfile.DEFAULT_PRODUCTION_DIR_NAME, srcDirName)) {
+ addChild(element, "sourceOutputDir").setAttribute(NAME, srcDirName);
+ }
+ final String testSrcDirName = profile.getGeneratedSourcesDirectoryName(true);
+ if (!StringUtil.equals(ProcessorConfigProfile.DEFAULT_TESTS_DIR_NAME, testSrcDirName)) {
+ addChild(element, "sourceTestOutputDir").setAttribute(NAME, testSrcDirName);
+ }
+
+ if (profile.isOutputRelativeToContentRoot()) {
+ addChild(element, "outputRelativeToContentRoot").setAttribute(VALUE, "true");
+ }
+
+ final Map<String, String> options = profile.getProcessorOptions();
+ if (!options.isEmpty()) {
+ final List<String> keys = new ArrayList<String>(options.keySet());
+ Collections.sort(keys, ALPHA_COMPARATOR);
+ for (String key : keys) {
+ addChild(element, OPTION).setAttribute(NAME, key).setAttribute(VALUE, options.get(key));
+ }
+ }
+
+ final Set<String> processors = profile.getProcessors();
+ if (!processors.isEmpty()) {
+ final List<String> processorList = new ArrayList<String>(processors);
+ Collections.sort(processorList, ALPHA_COMPARATOR);
+ for (String proc : processorList) {
+ addChild(element, "processor").setAttribute(NAME, proc);
+ }
+ }
+
+ final Element pathElement = addChild(element, "processorPath").setAttribute("useClasspath", Boolean.toString(
+ profile.isObtainProcessorsFromClasspath()));
+ final String path = profile.getProcessorPath();
+ if (!StringUtil.isEmpty(path)) {
+ final StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator, false);
+ while (tokenizer.hasMoreTokens()) {
+ final String token = tokenizer.nextToken();
+ addChild(pathElement, ENTRY).setAttribute(NAME, FileUtil.toSystemIndependentName(token));
+ }
+ }
+
+ final Set<String> moduleNames = profile.getModuleNames();
+ if (!moduleNames.isEmpty()) {
+ final List<String> names = new ArrayList<String>(moduleNames);
+ Collections.sort(names, ALPHA_COMPARATOR);
+ for (String name : names) {
+ addChild(element, MODULE).setAttribute(NAME, name);
+ }
+ }
+ }
+
+ private static Element addChild(Element parent, final String childName) {
+ final Element child = new Element(childName);
+ parent.addContent(child);
+ return child;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsEclipseCompilerOptionsSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsEclipseCompilerOptionsSerializer.java
new file mode 100644
index 000000000000..b3c549fe576f
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsEclipseCompilerOptionsSerializer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.EclipseCompilerOptions;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+
+/**
+ * @author nik
+ */
+public class JpsEclipseCompilerOptionsSerializer extends JpsProjectExtensionSerializer {
+ private final String myCompilerId;
+
+ public JpsEclipseCompilerOptionsSerializer(String componentName, String compilerId) {
+ super("compiler.xml", componentName);
+ myCompilerId = compilerId;
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ EclipseCompilerOptions options = XmlSerializer.deserialize(componentTag, EclipseCompilerOptions.class);
+ if (options == null) {
+ options = new EclipseCompilerOptions();
+ }
+ configuration.setCompilerOptions(myCompilerId, options);
+ }
+
+ @Override
+ public void loadExtensionWithDefaultSettings(@NotNull JpsProject project) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ configuration.setCompilerOptions(myCompilerId, new EclipseCompilerOptions());
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java
new file mode 100644
index 000000000000..b5cefb3b8b06
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.openapi.util.JDOMExternalizerUtil;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsJavaCompilerConfigurationSerializer extends JpsProjectExtensionSerializer {
+ public static final String EXCLUDE_FROM_COMPILE = "excludeFromCompile";
+ public static final String RESOURCE_EXTENSIONS = "resourceExtensions";
+ public static final String ANNOTATION_PROCESSING = "annotationProcessing";
+ public static final String BYTECODE_TARGET_LEVEL = "bytecodeTargetLevel";
+ public static final String WILDCARD_RESOURCE_PATTERNS = "wildcardResourcePatterns";
+ public static final String ADD_NOTNULL_ASSERTIONS = "addNotNullAssertions";
+ public static final String ENTRY = "entry";
+ public static final String NAME = "name";
+ public static final String ENABLED = "enabled";
+ public static final String MODULE = "module";
+ public static final String TARGET_ATTRIBUTE = "target";
+
+ public JpsJavaCompilerConfigurationSerializer() {
+ super("compiler.xml", "CompilerConfiguration");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ Element addNotNullTag = componentTag.getChild(ADD_NOTNULL_ASSERTIONS);
+ if (addNotNullTag != null) {
+ configuration.setAddNotNullAssertions(Boolean.parseBoolean(addNotNullTag.getAttributeValue(ENABLED, "true")));
+ }
+
+ Element excludeFromCompileTag = componentTag.getChild(EXCLUDE_FROM_COMPILE);
+ if (excludeFromCompileTag != null) {
+ for (Element fileTag : JDOMUtil.getChildren(excludeFromCompileTag, "file")) {
+ configuration.getCompilerExcludes().addExcludedFile(fileTag.getAttributeValue("url"));
+ }
+ for (Element directoryTag : JDOMUtil.getChildren(excludeFromCompileTag, "directory")) {
+ boolean recursively = Boolean.parseBoolean(directoryTag.getAttributeValue("includeSubdirectories"));
+ configuration.getCompilerExcludes().addExcludedDirectory(directoryTag.getAttributeValue("url"), recursively);
+ }
+ }
+
+ Element resourcePatternsTag = componentTag.getChild(WILDCARD_RESOURCE_PATTERNS);
+ for (Element entry : JDOMUtil.getChildren(resourcePatternsTag, ENTRY)) {
+ String pattern = entry.getAttributeValue(NAME);
+ if (!StringUtil.isEmpty(pattern)) {
+ configuration.addResourcePattern(pattern);
+ }
+ }
+
+ Element annotationProcessingTag = componentTag.getChild(ANNOTATION_PROCESSING);
+ if (annotationProcessingTag != null) {
+ List<Element> profiles = JDOMUtil.getChildren(annotationProcessingTag, "profile");
+ for (Element profileTag : profiles) {
+ boolean isDefault = Boolean.parseBoolean(profileTag.getAttributeValue("default"));
+ if (isDefault) {
+ AnnotationProcessorProfileSerializer.readExternal(configuration.getDefaultAnnotationProcessingProfile(), profileTag);
+ }
+ else {
+ AnnotationProcessorProfileSerializer.readExternal(configuration.addAnnotationProcessingProfile(), profileTag);
+ }
+ }
+ }
+
+ Element targetLevelTag = componentTag.getChild(BYTECODE_TARGET_LEVEL);
+ if (targetLevelTag != null) {
+ configuration.setProjectByteCodeTargetLevel(targetLevelTag.getAttributeValue(TARGET_ATTRIBUTE));
+ for (Element moduleTag : JDOMUtil.getChildren(targetLevelTag, MODULE)) {
+ String moduleName = moduleTag.getAttributeValue(NAME);
+ String level = moduleTag.getAttributeValue(TARGET_ATTRIBUTE);
+ if (moduleName != null && level != null) {
+ configuration.setModuleByteCodeTargetLevel(moduleName, level);
+ }
+ }
+ }
+ String compilerId = JDOMExternalizerUtil.readField(componentTag, "DEFAULT_COMPILER");
+ if (compilerId != null) {
+ configuration.setJavaCompilerId(compilerId);
+ }
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerOptionsSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerOptionsSerializer.java
new file mode 100644
index 000000000000..fa5a7d451fb3
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerOptionsSerializer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+
+/**
+ * @author nik
+ */
+public class JpsJavaCompilerOptionsSerializer extends JpsProjectExtensionSerializer {
+ private final String myCompilerId;
+
+ public JpsJavaCompilerOptionsSerializer(String componentName, String compilerId) {
+ super("compiler.xml", componentName);
+ myCompilerId = compilerId;
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ JpsJavaCompilerOptions options = XmlSerializer.deserialize(componentTag, JpsJavaCompilerOptions.class);
+ if (options == null) {
+ options = new JpsJavaCompilerOptions();
+ }
+ configuration.setCompilerOptions(myCompilerId, options);
+ }
+
+ @Override
+ public void loadExtensionWithDefaultSettings(@NotNull JpsProject project) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ configuration.setCompilerOptions(myCompilerId, new JpsJavaCompilerOptions());
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerWorkspaceConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerWorkspaceConfigurationSerializer.java
new file mode 100644
index 000000000000..462309da1480
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerWorkspaceConfigurationSerializer.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.openapi.util.JDOMExternalizerUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+
+/**
+ * @author nik
+ */
+public class JpsJavaCompilerWorkspaceConfigurationSerializer extends JpsProjectExtensionSerializer {
+ public JpsJavaCompilerWorkspaceConfigurationSerializer() {
+ super(WORKSPACE_FILE, "CompilerWorkspaceConfiguration");
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ String assertNotNull = JDOMExternalizerUtil.readField(componentTag, "ASSERT_NOT_NULL");
+ if (assertNotNull != null) {
+ configuration.setAddNotNullAssertions(Boolean.parseBoolean(assertNotNull));
+ }
+ String clearOutputDirectory = JDOMExternalizerUtil.readField(componentTag, "CLEAR_OUTPUT_DIRECTORY");
+ configuration.setClearOutputDirectoryOnRebuild(clearOutputDirectory == null || Boolean.parseBoolean(clearOutputDirectory));
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/RmicCompilerOptionsSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/RmicCompilerOptionsSerializer.java
new file mode 100644
index 000000000000..015a62ce3b15
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/RmicCompilerOptionsSerializer.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.java.compiler;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.RmicCompilerOptions;
+import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
+
+/**
+ * @author nik
+ */
+public class RmicCompilerOptionsSerializer extends JpsProjectExtensionSerializer {
+ private final String myCompilerId;
+
+ public RmicCompilerOptionsSerializer(String componentName, String compilerId) {
+ super("compiler.xml", componentName);
+ myCompilerId = compilerId;
+ }
+
+ @Override
+ public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ RmicCompilerOptions options = XmlSerializer.deserialize(componentTag, RmicCompilerOptions.class);
+ configuration.setCompilerOptions(myCompilerId, options == null? new RmicCompilerOptions() : options);
+ }
+
+ @Override
+ public void loadExtensionWithDefaultSettings(@NotNull JpsProject project) {
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ configuration.setCompilerOptions(myCompilerId, new RmicCompilerOptions());
+ }
+
+ @Override
+ public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryPropertiesSerializer.java
new file mode 100644
index 000000000000..c9b746371569
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryPropertiesSerializer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.library;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.library.JpsLibraryType;
+import org.jetbrains.jps.model.serialization.JpsElementPropertiesSerializer;
+
+/**
+ * @author nik
+ */
+public abstract class JpsLibraryPropertiesSerializer<P extends JpsElement> extends JpsElementPropertiesSerializer<P, JpsLibraryType<P>> {
+ public JpsLibraryPropertiesSerializer(JpsLibraryType<P> type, String typeId) {
+ super(type, typeId);
+ }
+
+ public abstract P loadProperties(@Nullable Element propertiesElement);
+
+ public abstract void saveProperties(P properties, Element element);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryRootTypeSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryRootTypeSerializer.java
new file mode 100644
index 000000000000..e51499f924af
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryRootTypeSerializer.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.library;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryRootTypeSerializer implements Comparable<JpsLibraryRootTypeSerializer> {
+ private String myTypeId;
+ private JpsOrderRootType myType;
+ private boolean myWriteIfEmpty;
+
+ public JpsLibraryRootTypeSerializer(@NotNull String typeId, @NotNull JpsOrderRootType type, boolean writeIfEmpty) {
+ myTypeId = typeId;
+ myType = type;
+ myWriteIfEmpty = writeIfEmpty;
+ }
+
+ public boolean isWriteIfEmpty() {
+ return myWriteIfEmpty;
+ }
+
+ public String getTypeId() {
+ return myTypeId;
+ }
+
+ public JpsOrderRootType getType() {
+ return myType;
+ }
+
+ @Override
+ public int compareTo(JpsLibraryRootTypeSerializer o) {
+ return myTypeId.compareTo(o.myTypeId);
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryTableSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryTableSerializer.java
new file mode 100644
index 000000000000..659d2d2420e2
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsLibraryTableSerializer.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.library;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.util.containers.MultiMap;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.*;
+import org.jetbrains.jps.model.java.JpsJavaLibraryType;
+import org.jetbrains.jps.model.library.*;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.JpsModuleReference;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JpsLibraryTableSerializer {
+ private static final JpsLibraryRootTypeSerializer[] PREDEFINED_ROOT_TYPES_SERIALIZERS = {
+ new JpsLibraryRootTypeSerializer("CLASSES", JpsOrderRootType.COMPILED, true),
+ new JpsLibraryRootTypeSerializer("SOURCES", JpsOrderRootType.SOURCES, true)
+ };
+ private static final String NAME_ATTRIBUTE = "name";
+ private static final String TYPE_ATTRIBUTE = "type";
+ private static final String PROPERTIES_TAG = "properties";
+ private static final String JAR_DIRECTORY_TAG = "jarDirectory";
+ private static final String URL_ATTRIBUTE = "url";
+ private static final String ROOT_TAG = "root";
+ private static final String RECURSIVE_ATTRIBUTE = "recursive";
+ private static final String LIBRARY_TAG = "library";
+ private static final JpsLibraryPropertiesSerializer<JpsDummyElement> JAVA_LIBRARY_PROPERTIES_SERIALIZER =
+ new JpsLibraryPropertiesSerializer<JpsDummyElement>(JpsJavaLibraryType.INSTANCE, null) {
+ @Override
+ public JpsDummyElement loadProperties(@Nullable Element propertiesElement) {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+
+ @Override
+ public void saveProperties(JpsDummyElement properties, Element element) {
+ }
+ };
+ private static final String MODULE_LEVEL = "module";
+ private static final String PROJECT_LEVEL = "project";
+ private static final String APPLICATION_LEVEL = "application";
+
+ public static void loadLibraries(@Nullable Element libraryTableElement, JpsLibraryCollection result) {
+ for (Element libraryElement : JDOMUtil.getChildren(libraryTableElement, LIBRARY_TAG)) {
+ result.addLibrary(loadLibrary(libraryElement));
+ }
+ }
+
+ public static void saveLibraries(JpsLibraryCollection libraryCollection, Element libraryTableElement) {
+ List<JpsLibrary> libraries = new ArrayList<JpsLibrary>();
+ for (JpsLibrary library : libraryCollection.getLibraries()) {
+ if (!(library.getType() instanceof JpsSdkType<?>)) {
+ libraries.add(library);
+ }
+ }
+
+ Collections.sort(libraries, new Comparator<JpsLibrary>() {
+ @Override
+ public int compare(JpsLibrary o1, JpsLibrary o2) {
+ return o1.getName().compareToIgnoreCase(o2.getName());
+ }
+ });
+
+ for (JpsLibrary library : libraries) {
+ Element libraryTag = new Element(LIBRARY_TAG);
+ saveLibrary(library, libraryTag, library.getName());
+ libraryTableElement.addContent(libraryTag);
+ }
+ }
+
+ public static JpsLibrary loadLibrary(Element libraryElement) {
+ return loadLibrary(libraryElement, libraryElement.getAttributeValue(NAME_ATTRIBUTE));
+ }
+
+ public static JpsLibrary loadLibrary(Element libraryElement, String name) {
+ String typeId = libraryElement.getAttributeValue(TYPE_ATTRIBUTE);
+ final JpsLibraryPropertiesSerializer<?> loader = getLibraryPropertiesSerializer(typeId);
+ JpsLibrary library = createLibrary(name, loader, libraryElement.getChild(PROPERTIES_TAG));
+
+ MultiMap<JpsOrderRootType, String> jarDirectories = new MultiMap<JpsOrderRootType, String>();
+ MultiMap<JpsOrderRootType, String> recursiveJarDirectories = new MultiMap<JpsOrderRootType, String>();
+ for (Element jarDirectory : JDOMUtil.getChildren(libraryElement, JAR_DIRECTORY_TAG)) {
+ String url = jarDirectory.getAttributeValue(URL_ATTRIBUTE);
+ String rootTypeId = jarDirectory.getAttributeValue(TYPE_ATTRIBUTE);
+ final JpsOrderRootType rootType = rootTypeId != null ? getRootType(rootTypeId) : JpsOrderRootType.COMPILED;
+ boolean recursive = Boolean.parseBoolean(jarDirectory.getAttributeValue(RECURSIVE_ATTRIBUTE));
+ jarDirectories.putValue(rootType, url);
+ if (recursive) {
+ recursiveJarDirectories.putValue(rootType, url);
+ }
+ }
+ for (Element rootsElement : JDOMUtil.getChildren(libraryElement)) {
+ final String rootTypeId = rootsElement.getName();
+ if (!rootTypeId.equals(JAR_DIRECTORY_TAG)) {
+ final JpsOrderRootType rootType = getRootType(rootTypeId);
+ for (Element rootElement : JDOMUtil.getChildren(rootsElement, ROOT_TAG)) {
+ String url = rootElement.getAttributeValue(URL_ATTRIBUTE);
+ JpsLibraryRoot.InclusionOptions options;
+ if (jarDirectories.get(rootType).contains(url)) {
+ final boolean recursive = recursiveJarDirectories.get(rootType).contains(url);
+ options = recursive ? JpsLibraryRoot.InclusionOptions.ARCHIVES_UNDER_ROOT_RECURSIVELY : JpsLibraryRoot.InclusionOptions.ARCHIVES_UNDER_ROOT;
+ }
+ else {
+ options = JpsLibraryRoot.InclusionOptions.ROOT_ITSELF;
+ }
+ library.addRoot(url, rootType, options);
+ }
+ }
+ }
+ return library;
+ }
+
+ public static void saveLibrary(JpsLibrary library, Element libraryElement, final String libraryName) {
+ if (libraryName != null) {
+ libraryElement.setAttribute(NAME_ATTRIBUTE, libraryName);
+ }
+ saveProperties((JpsTypedLibrary<?>)library, libraryElement);
+ List<Element> jarDirectoryElements = new ArrayList<Element>();
+ for (JpsLibraryRootTypeSerializer serializer : getSortedSerializers()) {
+ List<JpsLibraryRoot> roots = library.getRoots(serializer.getType());
+ if (roots.isEmpty() && !serializer.isWriteIfEmpty()) continue;
+
+ Element typeElement = new Element(serializer.getTypeId());
+ for (JpsLibraryRoot root : roots) {
+ typeElement.addContent(new Element(ROOT_TAG).setAttribute(URL_ATTRIBUTE, root.getUrl()));
+ if (root.getInclusionOptions() != JpsLibraryRoot.InclusionOptions.ROOT_ITSELF) {
+ Element jarDirectoryElement = new Element(JAR_DIRECTORY_TAG).setAttribute(URL_ATTRIBUTE, root.getUrl());
+ boolean recursive = root.getInclusionOptions() == JpsLibraryRoot.InclusionOptions.ARCHIVES_UNDER_ROOT_RECURSIVELY;
+ jarDirectoryElement.setAttribute(RECURSIVE_ATTRIBUTE, Boolean.toString(recursive));
+ if (!serializer.getType().equals(JpsOrderRootType.COMPILED)) {
+ jarDirectoryElement.setAttribute(TYPE_ATTRIBUTE, serializer.getTypeId());
+ }
+ jarDirectoryElements.add(jarDirectoryElement);
+ }
+ }
+ libraryElement.addContent(typeElement);
+ }
+ libraryElement.addContent(jarDirectoryElements);
+ }
+
+ private static <P extends JpsElement> void saveProperties(JpsTypedLibrary<P> library, Element libraryElement) {
+ JpsLibraryType<P> type = library.getType();
+ if (!type.equals(JpsJavaLibraryType.INSTANCE)) {
+ JpsLibraryPropertiesSerializer<P> serializer = getLibraryPropertiesSerializer(type);
+ libraryElement.setAttribute(TYPE_ATTRIBUTE, serializer.getTypeId());
+ Element element = new Element(PROPERTIES_TAG);
+ serializer.saveProperties(library.getProperties(), element);
+ if (!element.getContent().isEmpty() || !element.getAttributes().isEmpty()) {
+ libraryElement.addContent(element);
+ }
+ }
+ }
+
+ private static <P extends JpsElement> JpsLibrary createLibrary(String name, JpsLibraryPropertiesSerializer<P> loader,
+ final Element propertiesElement) {
+ return JpsElementFactory.getInstance().createLibrary(name, loader.getType(), loader.loadProperties(propertiesElement));
+ }
+
+ private static JpsOrderRootType getRootType(String rootTypeId) {
+ for (JpsLibraryRootTypeSerializer serializer : PREDEFINED_ROOT_TYPES_SERIALIZERS) {
+ if (serializer.getTypeId().equals(rootTypeId)) {
+ return serializer.getType();
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsLibraryRootTypeSerializer serializer : extension.getLibraryRootTypeSerializers()) {
+ if (serializer.getTypeId().equals(rootTypeId)) {
+ return serializer.getType();
+ }
+ }
+ }
+ return JpsOrderRootType.COMPILED;
+ }
+
+ private static Collection<JpsLibraryRootTypeSerializer> getSortedSerializers() {
+ List<JpsLibraryRootTypeSerializer> serializers = new ArrayList<JpsLibraryRootTypeSerializer>();
+ Collections.addAll(serializers, PREDEFINED_ROOT_TYPES_SERIALIZERS);
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ serializers.addAll(extension.getLibraryRootTypeSerializers());
+ }
+ Collections.sort(serializers);
+ return serializers;
+ }
+
+ private static JpsLibraryPropertiesSerializer<?> getLibraryPropertiesSerializer(@Nullable String typeId) {
+ if (typeId != null) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsLibraryPropertiesSerializer<?> loader : extension.getLibraryPropertiesSerializers()) {
+ if (loader.getTypeId().equals(typeId)) {
+ return loader;
+ }
+ }
+ }
+ }
+ return JAVA_LIBRARY_PROPERTIES_SERIALIZER;
+ }
+
+ private static <P extends JpsElement> JpsLibraryPropertiesSerializer<P> getLibraryPropertiesSerializer(@NotNull JpsLibraryType<P> type) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsLibraryPropertiesSerializer<?> loader : extension.getLibraryPropertiesSerializers()) {
+ if (loader.getType().equals(type)) {
+ //noinspection unchecked
+ return (JpsLibraryPropertiesSerializer<P>)loader;
+ }
+ }
+ }
+ throw new IllegalArgumentException("unknown type library:" + type);
+ }
+
+ public static JpsElementReference<? extends JpsCompositeElement> createLibraryTableReference(String level) {
+ JpsElementFactory elementFactory = JpsElementFactory.getInstance();
+ if (level.equals(PROJECT_LEVEL)) {
+ return elementFactory.createProjectReference();
+ }
+ if (level.equals(APPLICATION_LEVEL)) {
+ return elementFactory.createGlobalReference();
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ final JpsElementReference<? extends JpsCompositeElement> reference = extension.createLibraryTableReference(level);
+ if (reference != null) {
+ return reference;
+ }
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ public static String getLevelId(JpsElementReference<? extends JpsCompositeElement> reference) {
+ if (reference instanceof JpsModuleReference) {
+ return MODULE_LEVEL;
+ }
+ JpsCompositeElement element = reference.resolve();
+ if (element instanceof JpsProject) {
+ return PROJECT_LEVEL;
+ }
+ else if (element instanceof JpsGlobal) {
+ return APPLICATION_LEVEL;
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ String levelId = extension.getLibraryTableLevelId(reference);
+ if (levelId != null) {
+ return levelId;
+ }
+ }
+ return null;
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkPropertiesSerializer.java
new file mode 100644
index 000000000000..67bbc4aca8ee
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkPropertiesSerializer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.library;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.serialization.JpsElementPropertiesSerializer;
+
+/**
+ * @author nik
+ */
+public abstract class JpsSdkPropertiesSerializer<P extends JpsElement> extends JpsElementPropertiesSerializer<P, JpsSdkType<P>> {
+
+ protected JpsSdkPropertiesSerializer(String typeId, JpsSdkType<P> type) {
+ super(type, typeId);
+ }
+
+ @NotNull
+ public abstract P loadProperties(@Nullable Element propertiesElement);
+
+ public abstract void saveProperties(@NotNull P properties, @NotNull Element element);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java
new file mode 100644
index 000000000000..b9840edb56de
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.library;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper;
+import org.jetbrains.jps.model.library.*;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.JpsSdkReferencesTable;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsSdkTableSerializer {
+ private static final Logger LOG = Logger.getInstance(JpsSdkTableSerializer.class);
+
+ private static final JpsLibraryRootTypeSerializer[] PREDEFINED_ROOT_TYPE_SERIALIZERS = {
+ new JpsLibraryRootTypeSerializer("classPath", JpsOrderRootType.COMPILED, true),
+ new JpsLibraryRootTypeSerializer("sourcePath", JpsOrderRootType.SOURCES, true)
+ };
+ private static final JpsSdkPropertiesSerializer<JpsDummyElement> JPS_JAVA_SDK_PROPERTIES_LOADER =
+ new JpsSdkPropertiesSerializer<JpsDummyElement>("JavaSDK", JpsJavaSdkType.INSTANCE) {
+ @NotNull
+ @Override
+ public JpsDummyElement loadProperties(Element propertiesElement) {
+ return JpsElementFactory.getInstance().createDummyElement();
+ }
+
+ @Override
+ public void saveProperties(@NotNull JpsDummyElement properties, @NotNull Element element) {
+ }
+ };
+ private static final String JDK_TAG = "jdk";
+ private static final String NAME_TAG = "name";
+ private static final String TYPE_TAG = "type";
+ private static final String TYPE_ATTRIBUTE = "type";
+ private static final String ROOTS_TAG = "roots";
+ private static final String ROOT_TAG = "root";
+ private static final String VERSION_TAG = "version";
+ private static final String HOME_PATH_TAG = "homePath";
+ private static final String VALUE_ATTRIBUTE = "value";
+ private static final String COMPOSITE_TYPE = "composite";
+ private static final String SIMPLE_TYPE = "simple";
+ private static final String URL_ATTRIBUTE = "url";
+ private static final String ADDITIONAL_TAG = "additional";
+
+ public static void loadSdks(@Nullable Element sdkListElement, JpsLibraryCollection result) {
+ for (Element sdkElement : JDOMUtil.getChildren(sdkListElement, JDK_TAG)) {
+ result.addLibrary(loadSdk(sdkElement));
+ }
+ }
+
+ public static void saveSdks(JpsLibraryCollection libraryCollection, Element sdkListElement) {
+ for (JpsLibrary library : libraryCollection.getLibraries()) {
+ JpsElement properties = library.getProperties();
+ if (properties instanceof JpsSdk<?>) {
+ Element sdkTag = new Element(JDK_TAG);
+ saveSdk((JpsSdk<?>)properties, sdkTag);
+ sdkListElement.addContent(sdkTag);
+ }
+ }
+ }
+
+ private static JpsLibrary loadSdk(Element sdkElement) {
+ String name = getAttributeValue(sdkElement, NAME_TAG);
+ String typeId = getAttributeValue(sdkElement, TYPE_TAG);
+ LOG.debug("Loading " + typeId + " SDK '" + name + "'");
+ JpsSdkPropertiesSerializer<?> serializer = getSdkPropertiesSerializer(typeId);
+ final JpsLibrary library = createSdk(name, serializer, sdkElement);
+ final Element roots = sdkElement.getChild(ROOTS_TAG);
+ for (Element rootTypeElement : JDOMUtil.getChildren(roots)) {
+ JpsLibraryRootTypeSerializer rootTypeSerializer = getRootTypeSerializer(rootTypeElement.getName());
+ if (rootTypeSerializer != null) {
+ for (Element rootElement : JDOMUtil.getChildren(rootTypeElement)) {
+ loadRoots(rootElement, library, rootTypeSerializer.getType());
+ }
+ }
+ else {
+ LOG.info("root type serializer not found for " + rootTypeElement.getName());
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ List<File> files = library.getFiles(JpsOrderRootType.COMPILED);
+ LOG.debug(name + " SDK classpath (" + files.size() + " roots):");
+ for (File file : files) {
+ LOG.debug(" " + file.getAbsolutePath());
+ }
+ }
+ return library;
+ }
+
+ private static <P extends JpsElement> void saveSdk(final JpsSdk<P> sdk, Element sdkTag) {
+ JpsLibrary library = sdk.getParent();
+ sdkTag.setAttribute("version", "2");
+ setAttributeValue(sdkTag, NAME_TAG, library.getName());
+ JpsSdkPropertiesSerializer<P> serializer = getSdkPropertiesSerializer(sdk.getSdkType());
+ setAttributeValue(sdkTag, TYPE_TAG, serializer.getTypeId());
+ String versionString = sdk.getVersionString();
+ if (versionString != null) {
+ setAttributeValue(sdkTag, VERSION_TAG, versionString);
+ }
+ setAttributeValue(sdkTag, HOME_PATH_TAG, sdk.getHomePath());
+
+ Element rootsTag = new Element(ROOTS_TAG);
+ for (JpsLibraryRootTypeSerializer rootTypeSerializer : getRootTypeSerializers()) {
+ Element rootTypeTag = new Element(rootTypeSerializer.getTypeId());
+ Element compositeTag = new Element(ROOT_TAG);
+ compositeTag.setAttribute(TYPE_ATTRIBUTE, COMPOSITE_TYPE);
+ List<JpsLibraryRoot> roots = library.getRoots(rootTypeSerializer.getType());
+ for (JpsLibraryRoot root : roots) {
+ compositeTag.addContent(new Element(ROOT_TAG).setAttribute(TYPE_ATTRIBUTE, SIMPLE_TYPE).setAttribute(URL_ATTRIBUTE, root.getUrl()));
+ }
+ rootTypeTag.addContent(compositeTag);
+ rootsTag.addContent(rootTypeTag);
+ }
+ sdkTag.addContent(rootsTag);
+
+ Element additionalTag = new Element(ADDITIONAL_TAG);
+ serializer.saveProperties(sdk.getSdkProperties(), additionalTag);
+ sdkTag.addContent(additionalTag);
+ }
+
+ private static void setAttributeValue(Element tag, final String tagName, final String value) {
+ tag.addContent(new Element(tagName).setAttribute(VALUE_ATTRIBUTE, value));
+ }
+
+ private static void loadRoots(Element rootElement, JpsLibrary library, JpsOrderRootType rootType) {
+ final String type = rootElement.getAttributeValue(TYPE_ATTRIBUTE);
+ if (type.equals(COMPOSITE_TYPE)) {
+ for (Element element : JDOMUtil.getChildren(rootElement)) {
+ loadRoots(element, library, rootType);
+ }
+ }
+ else if (type.equals(SIMPLE_TYPE)) {
+ library.addRoot(rootElement.getAttributeValue(URL_ATTRIBUTE), rootType);
+ }
+ }
+
+ @Nullable
+ private static JpsLibraryRootTypeSerializer getRootTypeSerializer(String typeId) {
+ for (JpsLibraryRootTypeSerializer serializer : PREDEFINED_ROOT_TYPE_SERIALIZERS) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsLibraryRootTypeSerializer serializer : extension.getSdkRootTypeSerializers()) {
+ if (serializer.getTypeId().equals(typeId)) {
+ return serializer;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static List<JpsLibraryRootTypeSerializer> getRootTypeSerializers() {
+ List<JpsLibraryRootTypeSerializer> serializers = new ArrayList<JpsLibraryRootTypeSerializer>(Arrays.asList(PREDEFINED_ROOT_TYPE_SERIALIZERS));
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ serializers.addAll(extension.getSdkRootTypeSerializers());
+ }
+ Collections.sort(serializers);
+ return serializers;
+ }
+
+ private static <P extends JpsElement> JpsLibrary createSdk(String name, JpsSdkPropertiesSerializer<P> loader, Element sdkElement) {
+ String versionString = getAttributeValue(sdkElement, VERSION_TAG);
+ String homePath = getAttributeValue(sdkElement, HOME_PATH_TAG);
+ Element propertiesTag = sdkElement.getChild(ADDITIONAL_TAG);
+ P properties = loader.loadProperties(propertiesTag);
+ return JpsElementFactory.getInstance().createSdk(name, homePath, versionString, loader.getType(), properties);
+ }
+
+ public static JpsSdkPropertiesSerializer<?> getSdkPropertiesSerializer(@Nullable String typeId) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsSdkPropertiesSerializer<?> loader : extension.getSdkPropertiesSerializers()) {
+ if (loader.getTypeId().equals(typeId)) {
+ return loader;
+ }
+ }
+ }
+ return JPS_JAVA_SDK_PROPERTIES_LOADER;
+ }
+
+ public static <P extends JpsElement> JpsSdkPropertiesSerializer<P> getSdkPropertiesSerializer(JpsSdkType<P> type) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsSdkPropertiesSerializer<?> loader : extension.getSdkPropertiesSerializers()) {
+ if (loader.getType().equals(type)) {
+ //noinspection unchecked
+ return (JpsSdkPropertiesSerializer<P>)loader;
+ }
+ }
+ }
+ //noinspection unchecked
+ return (JpsSdkPropertiesSerializer<P>)JPS_JAVA_SDK_PROPERTIES_LOADER;
+ }
+
+ @Nullable
+ private static String getAttributeValue(Element element, String childName) {
+ final Element child = element.getChild(childName);
+ return child != null ? child.getAttributeValue(VALUE_ATTRIBUTE) : null;
+ }
+
+ public static JpsSdkType<?> getSdkType(@Nullable String typeId) {
+ return getSdkPropertiesSerializer(typeId).getType();
+ }
+
+ public static JpsSdkPropertiesSerializer<?> getLoader(JpsSdkType<?> type) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsSdkPropertiesSerializer<?> loader : extension.getSdkPropertiesSerializers()) {
+ if (loader.getType().equals(type)) {
+ return loader;
+ }
+ }
+ }
+ return JPS_JAVA_SDK_PROPERTIES_LOADER;
+ }
+
+ public static <P extends JpsElement> void setSdkReference(final JpsSdkReferencesTable table, String sdkName, JpsSdkType<P> sdkType) {
+ JpsSdkReference<P> reference = JpsElementFactory.getInstance().createSdkReference(sdkName, sdkType);
+ table.setSdkReference(sdkType, reference);
+ if (sdkType instanceof JpsJavaSdkTypeWrapper) {
+ JpsSdkReference<P> wrapperRef = JpsElementFactory.getInstance().createSdkReference(sdkName, sdkType);
+ table.setSdkReference(JpsJavaSdkType.INSTANCE, JpsJavaExtensionService.getInstance().createWrappedJavaSdkReference((JpsJavaSdkTypeWrapper)sdkType,
+ wrapperRef));
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleClasspathSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleClasspathSerializer.java
new file mode 100644
index 000000000000..d6e1b21fd885
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleClasspathSerializer.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsMacroExpander;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModuleClasspathSerializer {
+ private final String myClasspathId;
+
+ protected JpsModuleClasspathSerializer(String classpathId) {
+ myClasspathId = classpathId;
+ }
+
+ public final String getClasspathId() {
+ return myClasspathId;
+ }
+
+ public abstract void loadClasspath(@NotNull JpsModule module,
+ @Nullable String classpathDir,
+ @NotNull String baseModulePath,
+ JpsMacroExpander expander,
+ List<String> paths,
+ JpsSdkType<?> projectSdkType);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModulePropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModulePropertiesSerializer.java
new file mode 100644
index 000000000000..5510ee4a5551
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModulePropertiesSerializer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.module;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.model.serialization.JpsElementPropertiesSerializer;
+
+/**
+ * @author nik
+ */
+public abstract class JpsModulePropertiesSerializer<P extends JpsElement> extends JpsElementPropertiesSerializer<P, JpsModuleType<P>> {
+ private final String myComponentName;
+
+ protected JpsModulePropertiesSerializer(JpsModuleType<P> type, String typeId, @Nullable String componentName) {
+ super(type, typeId);
+ myComponentName = componentName;
+ }
+
+ @Nullable
+ public String getComponentName() {
+ return myComponentName;
+ }
+
+ public abstract P loadProperties(@Nullable Element componentElement);
+
+ public abstract void saveProperties(@NotNull P properties, @NotNull Element componentElement);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
new file mode 100644
index 000000000000..2f281130f0ff
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.module;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsCompositeElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsElementReference;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsLibraryReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.*;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
+import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.openapi.util.JDOMUtil.getChildren;
+
+/**
+ * @author nik
+ */
+public class JpsModuleRootModelSerializer {
+ public static final String URL_ATTRIBUTE = "url";
+ public static final String CONTENT_TAG = "content";
+ public static final String SOURCE_FOLDER_TAG = "sourceFolder";
+ public static final String PACKAGE_PREFIX_ATTRIBUTE = "packagePrefix";
+ public static final String IS_TEST_SOURCE_ATTRIBUTE = "isTestSource";
+ public static final String EXCLUDE_FOLDER_TAG = "excludeFolder";
+ public static final String ORDER_ENTRY_TAG = "orderEntry";
+ public static final String TYPE_ATTRIBUTE = "type";
+ public static final String SOURCE_FOLDER_TYPE = "sourceFolder";
+ public static final String JDK_TYPE = "jdk";
+ public static final String JDK_NAME_ATTRIBUTE = "jdkName";
+ public static final String JDK_TYPE_ATTRIBUTE = "jdkType";
+ public static final String INHERITED_JDK_TYPE = "inheritedJdk";
+ public static final String LIBRARY_TYPE = "library";
+ public static final String NAME_ATTRIBUTE = "name";
+ public static final String LEVEL_ATTRIBUTE = "level";
+ public static final String LIBRARY_TAG = "library";
+ public static final String MODULE_LIBRARY_TYPE = "module-library";
+ public static final String MODULE_TYPE = "module";
+ public static final String MODULE_NAME_ATTRIBUTE = "module-name";
+ private static final String GENERATED_LIBRARY_NAME_PREFIX = "#";
+
+ public static void loadRootModel(JpsModule module, @Nullable Element rootModelComponent, @Nullable JpsSdkType<?> projectSdkType) {
+ if (rootModelComponent == null) return;
+
+ for (Element contentElement : getChildren(rootModelComponent, CONTENT_TAG)) {
+ final String url = contentElement.getAttributeValue(URL_ATTRIBUTE);
+ module.getContentRootsList().addUrl(url);
+ for (Element sourceElement : getChildren(contentElement, SOURCE_FOLDER_TAG)) {
+ final String sourceUrl = sourceElement.getAttributeValue(URL_ATTRIBUTE);
+ final String packagePrefix = StringUtil.notNullize(sourceElement.getAttributeValue(PACKAGE_PREFIX_ATTRIBUTE));
+ final boolean testSource = Boolean.parseBoolean(sourceElement.getAttributeValue(IS_TEST_SOURCE_ATTRIBUTE));
+ final JavaSourceRootType rootType = testSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+ module.addSourceRoot(sourceUrl, rootType, JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties(packagePrefix)));
+ }
+ for (Element excludeElement : getChildren(contentElement, EXCLUDE_FOLDER_TAG)) {
+ module.getExcludeRootsList().addUrl(excludeElement.getAttributeValue(URL_ATTRIBUTE));
+ }
+ }
+
+ final JpsDependenciesList dependenciesList = module.getDependenciesList();
+ dependenciesList.clear();
+ final JpsElementFactory elementFactory = JpsElementFactory.getInstance();
+ int moduleLibraryNum = 0;
+ for (Element orderEntry : getChildren(rootModelComponent, ORDER_ENTRY_TAG)) {
+ String type = orderEntry.getAttributeValue(TYPE_ATTRIBUTE);
+ if (SOURCE_FOLDER_TYPE.equals(type)) {
+ dependenciesList.addModuleSourceDependency();
+ }
+ else if (JDK_TYPE.equals(type)) {
+ String sdkName = orderEntry.getAttributeValue(JDK_NAME_ATTRIBUTE);
+ String sdkTypeId = orderEntry.getAttributeValue(JDK_TYPE_ATTRIBUTE);
+ final JpsSdkType<?> sdkType = JpsSdkTableSerializer.getSdkType(sdkTypeId);
+ dependenciesList.addSdkDependency(sdkType);
+ JpsSdkTableSerializer.setSdkReference(module.getSdkReferencesTable(), sdkName, sdkType);
+ if (sdkType instanceof JpsJavaSdkTypeWrapper) {
+ dependenciesList.addSdkDependency(JpsJavaSdkType.INSTANCE);
+ }
+ }
+ else if (INHERITED_JDK_TYPE.equals(type)) {
+ dependenciesList.addSdkDependency(projectSdkType != null ? projectSdkType : JpsJavaSdkType.INSTANCE);
+ }
+ else if (LIBRARY_TYPE.equals(type)) {
+ String name = orderEntry.getAttributeValue(NAME_ATTRIBUTE);
+ String level = orderEntry.getAttributeValue(LEVEL_ATTRIBUTE);
+ final JpsLibraryDependency dependency =
+ dependenciesList.addLibraryDependency(elementFactory.createLibraryReference(name, JpsLibraryTableSerializer
+ .createLibraryTableReference(level)));
+ loadModuleDependencyProperties(dependency, orderEntry);
+ }
+ else if (MODULE_LIBRARY_TYPE.equals(type)) {
+ final Element moduleLibraryElement = orderEntry.getChild(LIBRARY_TAG);
+ String name = moduleLibraryElement.getAttributeValue(NAME_ATTRIBUTE);
+ if (name == null) {
+ name = GENERATED_LIBRARY_NAME_PREFIX + (moduleLibraryNum++);
+ }
+ final JpsLibrary library = JpsLibraryTableSerializer.loadLibrary(moduleLibraryElement, name);
+ module.addModuleLibrary(library);
+
+ final JpsLibraryDependency dependency = dependenciesList.addLibraryDependency(library);
+ loadModuleDependencyProperties(dependency, orderEntry);
+ moduleLibraryNum++;
+ }
+ else if (MODULE_TYPE.equals(type)) {
+ String name = orderEntry.getAttributeValue(MODULE_NAME_ATTRIBUTE);
+ final JpsModuleDependency dependency = dependenciesList.addModuleDependency(elementFactory.createModuleReference(name));
+ loadModuleDependencyProperties(dependency, orderEntry);
+ }
+ }
+
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ extension.loadRootModel(module, rootModelComponent);
+ }
+ }
+
+ public static void saveRootModel(JpsModule module, Element rootModelElement) {
+ List<JpsModuleSourceRoot> sourceRoots = module.getSourceRoots();
+ List<String> excludedUrls = getSortedList(module.getExcludeRootsList().getUrls());
+ for (String url : getSortedList(module.getContentRootsList().getUrls())) {
+ Element contentElement = new Element(CONTENT_TAG);
+ contentElement.setAttribute(URL_ATTRIBUTE, url);
+ rootModelElement.addContent(contentElement);
+ for (JpsModuleSourceRoot root : sourceRoots) {
+ if (FileUtil.startsWith(root.getUrl(), url)) {
+ Element sourceElement = new Element(SOURCE_FOLDER_TAG);
+ sourceElement.setAttribute(URL_ATTRIBUTE, root.getUrl());
+ JpsModuleSourceRootType<?> type = root.getRootType();
+ sourceElement.setAttribute(IS_TEST_SOURCE_ATTRIBUTE, Boolean.toString(type.equals(JavaSourceRootType.TEST_SOURCE)));
+ if (type instanceof JavaSourceRootType) {
+ JpsSimpleElement<JavaSourceRootProperties> properties = root.getProperties((JavaSourceRootType)type);
+ if (properties != null) {
+ String packagePrefix = properties.getData().getPackagePrefix();
+ if (packagePrefix.length() > 0) {
+ sourceElement.setAttribute(PACKAGE_PREFIX_ATTRIBUTE, packagePrefix);
+ }
+ }
+ }
+ contentElement.addContent(sourceElement);
+ }
+ }
+ for (String excludedUrl : excludedUrls) {
+ if (FileUtil.startsWith(excludedUrl, url)) {
+ Element element = new Element(EXCLUDE_FOLDER_TAG).setAttribute(URL_ATTRIBUTE, excludedUrl);
+ contentElement.addContent(element);
+ }
+ }
+ }
+
+ for (JpsDependencyElement dependency : module.getDependenciesList().getDependencies()) {
+ if (dependency instanceof JpsModuleSourceDependency) {
+ rootModelElement.addContent(createDependencyElement(SOURCE_FOLDER_TYPE).setAttribute("forTests", "false"));
+ }
+ else if (dependency instanceof JpsSdkDependency) {
+ JpsSdkType<?> sdkType = ((JpsSdkDependency)dependency).getSdkType();
+ JpsSdkReferencesTable table = module.getSdkReferencesTable();
+ JpsSdkReference<?> reference = table.getSdkReference(sdkType);
+ if (reference == null) {
+ rootModelElement.addContent(createDependencyElement(INHERITED_JDK_TYPE));
+ }
+ else {
+ Element element = createDependencyElement(JDK_TYPE);
+ element.setAttribute(JDK_NAME_ATTRIBUTE, reference.getSdkName());
+ element.setAttribute(JDK_TYPE_ATTRIBUTE, JpsSdkTableSerializer.getLoader(sdkType).getTypeId());
+ rootModelElement.addContent(element);
+ }
+ }
+ else if (dependency instanceof JpsLibraryDependency) {
+ JpsLibraryReference reference = ((JpsLibraryDependency)dependency).getLibraryReference();
+ JpsElementReference<? extends JpsCompositeElement> parentReference = reference.getParentReference();
+ Element element;
+ if (parentReference instanceof JpsModuleReference) {
+ element = createDependencyElement(MODULE_LIBRARY_TYPE);
+ saveModuleDependencyProperties(dependency, element);
+ Element libraryElement = new Element(LIBRARY_TAG);
+ JpsLibrary library = reference.resolve();
+ String libraryName = library.getName();
+ JpsLibraryTableSerializer.saveLibrary(library, libraryElement, isGeneratedName(libraryName) ? null : libraryName);
+ element.addContent(libraryElement);
+ }
+ else {
+ element = createDependencyElement(LIBRARY_TYPE);
+ saveModuleDependencyProperties(dependency, element);
+ element.setAttribute(NAME_ATTRIBUTE, reference.getLibraryName());
+ element.setAttribute(LEVEL_ATTRIBUTE, JpsLibraryTableSerializer.getLevelId(parentReference));
+ }
+ rootModelElement.addContent(element);
+ }
+ else if (dependency instanceof JpsModuleDependency) {
+ Element element = createDependencyElement(MODULE_TYPE);
+ element.setAttribute(MODULE_NAME_ATTRIBUTE, ((JpsModuleDependency)dependency).getModuleReference().getModuleName());
+ saveModuleDependencyProperties(dependency, element);
+ rootModelElement.addContent(element);
+ }
+ }
+
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ extension.saveRootModel(module, rootModelElement);
+ }
+ }
+
+ private static boolean isGeneratedName(String libraryName) {
+ return libraryName.startsWith(GENERATED_LIBRARY_NAME_PREFIX);
+ }
+
+ private static Element createDependencyElement(final String type) {
+ return new Element(ORDER_ENTRY_TAG).setAttribute(TYPE_ATTRIBUTE, type);
+ }
+
+ private static List<String> getSortedList(final List<String> list) {
+ List<String> strings = new ArrayList<String>(list);
+ Collections.sort(strings);
+ return strings;
+ }
+
+ private static void loadModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ extension.loadModuleDependencyProperties(dependency, orderEntry);
+ }
+ }
+
+ private static void saveModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ extension.saveModuleDependencyProperties(dependency, orderEntry);
+ }
+ }
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSerializationDataExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSerializationDataExtension.java
new file mode 100644
index 000000000000..49d02c20b700
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSerializationDataExtension.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.module;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface JpsModuleSerializationDataExtension extends JpsElement {
+ @NotNull
+ File getBaseDirectory();
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationPropertiesSerializer.java
new file mode 100644
index 000000000000..93675f324239
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationPropertiesSerializer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.runConfigurations;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.runConfiguration.JpsRunConfigurationType;
+import org.jetbrains.jps.model.serialization.JpsElementPropertiesSerializer;
+
+/**
+ * @author nik
+ */
+public abstract class JpsRunConfigurationPropertiesSerializer<P extends JpsElement> extends JpsElementPropertiesSerializer<P, JpsRunConfigurationType<P>> {
+ protected JpsRunConfigurationPropertiesSerializer(JpsRunConfigurationType<P> type, String typeId) {
+ super(type, typeId);
+ }
+
+ public abstract P loadProperties(@Nullable Element runConfigurationTag);
+
+ public abstract void saveProperties(P properties, Element runConfigurationTag);
+}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationSerializer.java
new file mode 100644
index 000000000000..6e619dc4c88c
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/runConfigurations/JpsRunConfigurationSerializer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization.runConfigurations;
+
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.util.containers.hash.HashMap;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class JpsRunConfigurationSerializer {
+ public static void loadRunConfigurations(@NotNull JpsProject project, @Nullable Element runManagerTag) {
+ Map<String, JpsRunConfigurationPropertiesSerializer<?>> serializers = new HashMap<String, JpsRunConfigurationPropertiesSerializer<?>>();
+ for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
+ for (JpsRunConfigurationPropertiesSerializer<?> serializer : extension.getRunConfigurationPropertiesSerializers()) {
+ serializers.put(serializer.getTypeId(), serializer);
+ }
+ }
+
+ for (Element configurationTag : JDOMUtil.getChildren(runManagerTag, "configuration")) {
+ if (Boolean.parseBoolean(configurationTag.getAttributeValue("default"))) {
+ continue;
+ }
+
+ String typeId = configurationTag.getAttributeValue("type");
+ JpsRunConfigurationPropertiesSerializer<?> serializer = serializers.get(typeId);
+ if (serializer != null) {
+ loadRunConfiguration(configurationTag, serializer, project);
+ }
+ }
+ }
+
+ private static <P extends JpsElement> void loadRunConfiguration(Element configurationTag,
+ JpsRunConfigurationPropertiesSerializer<P> serializer,
+ JpsProject project) {
+ P properties = serializer.loadProperties(configurationTag);
+ project.addRunConfiguration(configurationTag.getAttributeValue("name"), serializer.getType(), properties);
+
+ }
+}
diff --git a/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iml b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.ipr b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.ipr
new file mode 100644
index 000000000000..fbff622fda98
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.ipr
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <excludeFromCompile>
+ <directory url="file://$PROJECT_DIR$/src/nonrec" includeSubdirectories="false" />
+ <directory url="file://$PROJECT_DIR$/src/rec" includeSubdirectories="true" />
+ <file url="file://$PROJECT_DIR$/src/A.java" />
+ </excludeFromCompile>
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing>
+ <profile default="true" name="Default" enabled="true">
+ <sourceOutputDir name="gen" />
+ <option name="a" value="b" />
+ <option name="c" value="d" />
+ <processor name="my.proc" />
+ <processorPath useClasspath="false">
+ <entry name="$PROJECT_DIR$/src" />
+ </processorPath>
+ </profile>
+ </annotationProcessing>
+ </component>
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="false" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="-Xlint" />
+ <option name="MAXIMUM_HEAP_SIZE" value="512" />
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/compilerConfiguration.iml" filepath="$PROJECT_DIR$/compilerConfiguration.iml" />
+ </modules>
+ </component>
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iws b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iws
new file mode 100644
index 000000000000..8df8552f2cf0
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.iws
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerWorkspaceConfiguration">
+ <option name="CLEAR_OUTPUT_DIRECTORY" value="false" />
+ <option name="ASSERT_NOT_NULL" value="false" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/.idea/compiler.xml b/jps/model-serialization/testData/compilerConfigurationDir/.idea/compiler.xml
new file mode 100644
index 000000000000..9f7f048c049f
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/.idea/compiler.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <excludeFromCompile>
+ <directory url="file://$PROJECT_DIR$/src/nonrec" includeSubdirectories="false" />
+ <directory url="file://$PROJECT_DIR$/src/rec" includeSubdirectories="true" />
+ <file url="file://$PROJECT_DIR$/src/A.java" />
+ </excludeFromCompile>
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing>
+ <profile default="true" name="Default" enabled="true">
+ <sourceOutputDir name="gen" />
+ <option name="a" value="b" />
+ <option name="c" value="d" />
+ <processor name="my.proc" />
+ <processorPath useClasspath="false">
+ <entry name="$PROJECT_DIR$/src" />
+ </processorPath>
+ </profile>
+ </annotationProcessing>
+ </component>
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="false" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="-Xlint" />
+ <option name="MAXIMUM_HEAP_SIZE" value="512" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/.idea/encodings.xml b/jps/model-serialization/testData/compilerConfigurationDir/.idea/encodings.xml
new file mode 100644
index 000000000000..e206d70d8595
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/.idea/encodings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/.idea/misc.xml b/jps/model-serialization/testData/compilerConfigurationDir/.idea/misc.xml
new file mode 100644
index 000000000000..dc7535439d30
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/.idea/modules.xml b/jps/model-serialization/testData/compilerConfigurationDir/.idea/modules.xml
new file mode 100644
index 000000000000..8d836f64b0b9
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/compilerConfiguration.iml" filepath="$PROJECT_DIR$/compilerConfiguration.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/.idea/workspace.xml b/jps/model-serialization/testData/compilerConfigurationDir/.idea/workspace.xml
new file mode 100644
index 000000000000..8df8552f2cf0
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/.idea/workspace.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerWorkspaceConfiguration">
+ <option name="CLEAR_OUTPUT_DIRECTORY" value="false" />
+ <option name="ASSERT_NOT_NULL" value="false" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/compilerConfigurationDir/compilerConfiguration.iml b/jps/model-serialization/testData/compilerConfigurationDir/compilerConfiguration.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/model-serialization/testData/compilerConfigurationDir/compilerConfiguration.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/config/options/applicationLibraries.xml b/jps/model-serialization/testData/config/options/applicationLibraries.xml
new file mode 100644
index 000000000000..c12c635cbc00
--- /dev/null
+++ b/jps/model-serialization/testData/config/options/applicationLibraries.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+ <component name="libraryTable">
+ <library name="Gant">
+ <CLASSES>
+ <root url="jar://$USER_HOME$/applications/gant-1.9.2/lib/commons-cli-1.2.jar!/" />
+ <root url="jar://$USER_HOME$/applications/gant-1.9.2/lib/gant_groovy1.7-1.9.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </component>
+</application>
+
diff --git a/jps/model-serialization/testData/config/options/encoding.xml b/jps/model-serialization/testData/config/options/encoding.xml
new file mode 100644
index 000000000000..540f7793e7c7
--- /dev/null
+++ b/jps/model-serialization/testData/config/options/encoding.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+ <component name="Encoding" default_encoding="windows-1251" />
+</application>
+
diff --git a/jps/model-serialization/testData/config/options/filetypes.xml b/jps/model-serialization/testData/config/options/filetypes.xml
new file mode 100644
index 000000000000..c689f5650fd6
--- /dev/null
+++ b/jps/model-serialization/testData/config/options/filetypes.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+ <component name="FileTypeManager" version="11">
+ <ignoreFiles list="CVS;.svn;" />
+ <extensionMap>
+ <removed_mapping ext="feature" type="Cucumber" />
+ <mapping pattern="*.*Service" type="PLAIN_TEXT" />
+ <mapping ext="new" type="PLAIN_TEXT" />
+ <mapping ext="dup" type="PLAIN_TEXT" />
+ <mapping ext="jpx" type="PLAIN_TEXT" />
+ <mapping ext="pom" type="XML" />
+ </extensionMap>
+ </component>
+</application>
+
diff --git a/jps/model-serialization/testData/config/options/jdk.table.xml b/jps/model-serialization/testData/config/options/jdk.table.xml
new file mode 100644
index 000000000000..e20757865939
--- /dev/null
+++ b/jps/model-serialization/testData/config/options/jdk.table.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+ <component name="ProjectJdkTable">
+ <jdk version="2">
+ <name value="1.5" />
+ <type value="JavaSDK" />
+ <version value="java version &quot;1.5.0_21&quot;" />
+ <homePath value="$USER_HOME$/applications/jdk1.5.0_21" />
+ <roots>
+ <annotationsPath>
+ <root type="composite" />
+ </annotationsPath>
+ <classPath>
+ <root type="composite">
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.5.0_21/jre/lib/rt.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.5.0_21/jre/lib/plugin.jar!/" />
+ </root>
+ </classPath>
+ <javadocPath>
+ <root type="composite" />
+ </javadocPath>
+ <sourcePath>
+ <root type="composite">
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.5.0_21/src.zip!/" />
+ </root>
+ </sourcePath>
+ </roots>
+ <additional />
+ </jdk>
+ <jdk version="2">
+ <name value="1.6" />
+ <type value="JavaSDK" />
+ <version value="java version &quot;1.6.0_31&quot;" />
+ <homePath value="$USER_HOME$/applications/jdk1.6.0_31" />
+ <roots>
+ <annotationsPath>
+ <root type="composite">
+ <root type="simple" url="jar://$APPLICATION_HOME_DIR$/lib/jdkAnnotations.jar!/" />
+ </root>
+ </annotationsPath>
+ <classPath>
+ <root type="composite">
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/management-agent.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/plugin.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/rt.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/javaws.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/deploy.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/jsse.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/charsets.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/jce.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/resources.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/ext/sunpkcs11.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/ext/dnsns.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/ext/localedata.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/jre/lib/ext/sunjce_provider.jar!/" />
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/lib/tools.jar!/" />
+ </root>
+ </classPath>
+ <javadocPath>
+ <root type="composite" />
+ </javadocPath>
+ <sourcePath>
+ <root type="composite">
+ <root type="simple" url="jar://$USER_HOME$/applications/jdk1.6.0_31/src.zip!/" />
+ </root>
+ </sourcePath>
+ </roots>
+ <additional />
+ </jdk>
+ </component>
+</application>
+
diff --git a/jps/model-serialization/testData/fileEncoding/dir/with-encoding.xml b/jps/model-serialization/testData/fileEncoding/dir/with-encoding.xml
new file mode 100644
index 000000000000..3fb0f4d22133
--- /dev/null
+++ b/jps/model-serialization/testData/fileEncoding/dir/with-encoding.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<test/>
diff --git a/jps/model-serialization/testData/fileEncoding/dir/without-encoding.xml b/jps/model-serialization/testData/fileEncoding/dir/without-encoding.xml
new file mode 100644
index 000000000000..52e0a2001de9
--- /dev/null
+++ b/jps/model-serialization/testData/fileEncoding/dir/without-encoding.xml
@@ -0,0 +1 @@
+<test/> \ No newline at end of file
diff --git a/jps/model-serialization/testData/fileEncoding/fileEncoding.ipr b/jps/model-serialization/testData/fileEncoding/fileEncoding.ipr
new file mode 100644
index 000000000000..6a7bb958fa39
--- /dev/null
+++ b/jps/model-serialization/testData/fileEncoding/fileEncoding.ipr
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="UTF-8">
+ <file url="file://$PROJECT_DIR$/dir" charset="windows-1251" />
+ <file url="PROJECT" charset="UTF-8" />
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/imlUnderDotIdea/.idea/imlUnderDotIdea.iml b/jps/model-serialization/testData/imlUnderDotIdea/.idea/imlUnderDotIdea.iml
new file mode 100644
index 000000000000..26a958a9c8a4
--- /dev/null
+++ b/jps/model-serialization/testData/imlUnderDotIdea/.idea/imlUnderDotIdea.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/imlUnderDotIdea/.idea/misc.xml b/jps/model-serialization/testData/imlUnderDotIdea/.idea/misc.xml
new file mode 100644
index 000000000000..dc7535439d30
--- /dev/null
+++ b/jps/model-serialization/testData/imlUnderDotIdea/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/imlUnderDotIdea/.idea/modules.xml b/jps/model-serialization/testData/imlUnderDotIdea/.idea/modules.xml
new file mode 100644
index 000000000000..22ca31c6316a
--- /dev/null
+++ b/jps/model-serialization/testData/imlUnderDotIdea/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/imlUnderDotIdea.iml" filepath="$PROJECT_DIR$/.idea/imlUnderDotIdea.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/projectSdkWithoutType/projectSdkWithoutType.ipr b/jps/model-serialization/testData/projectSdkWithoutType/projectSdkWithoutType.ipr
new file mode 100644
index 000000000000..d9ae500f1f5d
--- /dev/null
+++ b/jps/model-serialization/testData/projectSdkWithoutType/projectSdkWithoutType.ipr
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" />
+</project>
+
diff --git a/jps/model-serialization/testData/run-configurations-dir/.idea/misc.xml b/jps/model-serialization/testData/run-configurations-dir/.idea/misc.xml
new file mode 100644
index 000000000000..94bc8fc64a28
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/run-configurations-dir/.idea/modules.xml b/jps/model-serialization/testData/run-configurations-dir/.idea/modules.xml
new file mode 100644
index 000000000000..29d91f22949a
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/run-configurations.iml" filepath="$PROJECT_DIR$/run-configurations.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/shared.xml b/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/shared.xml
new file mode 100644
index 000000000000..10ef6ba27c3b
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/shared.xml
@@ -0,0 +1,17 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="shared" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="xxx.Main2" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="run-configurations" />
+ <envs />
+ <method />
+ </configuration>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/test.xml b/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/test.xml
new file mode 100644
index 000000000000..189abcb66b1d
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/.idea/runConfigurations/test.xml
@@ -0,0 +1,23 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="test" type="JUnit" factoryName="JUnit">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="run-configurations" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" value="test.MyTest" />
+ <option name="METHOD_NAME" value="" />
+ <option name="TEST_OBJECT" value="class" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <envs />
+ <patterns />
+ <method />
+ </configuration>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/run-configurations-dir/.idea/workspace.xml b/jps/model-serialization/testData/run-configurations-dir/.idea/workspace.xml
new file mode 100644
index 000000000000..83beffbead44
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/.idea/workspace.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunManager" selected="Application.shared">
+ <configuration default="true" type="DartUnitRunConfigurationType" factoryName="DartUnit">
+ <option name="VMOptions" />
+ <option name="arguments" />
+ <option name="filePath" />
+ <option name="scope" value="ALL" />
+ <option name="testName" />
+ <method />
+ </configuration>
+ <configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
+ <module name="" />
+ <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m" />
+ <option name="PROGRAM_PARAMETERS" />
+ <method />
+ </configuration>
+ <configuration default="true" type="CapistranoRunConfigurationType" factoryName="Capistrano">
+ <module name="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="WORK DIR" VALUE="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="SHOULD_USE_SDK" VALUE="false" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="ALTERN_SDK_NAME" VALUE="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="myPassParentEnvs" VALUE="true" />
+ <envs />
+ <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
+ <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
+ <COVERAGE_PATTERN ENABLED="true">
+ <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
+ </COVERAGE_PATTERN>
+ </EXTENSION>
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_TASK_NAME" VALUE="" />
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_TASK_ARGS" VALUE="" />
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_STAGE" VALUE="" />
+ <method />
+ </configuration>
+ <configuration default="true" type="Remote" factoryName="Remote">
+ <option name="USE_SOCKET_TRANSPORT" value="true" />
+ <option name="SERVER_MODE" value="false" />
+ <option name="SHMEM_ADDRESS" value="javadebug" />
+ <option name="HOST" value="localhost" />
+ <option name="PORT" value="5005" />
+ <method />
+ </configuration>
+ <configuration default="true" type="TestNG" factoryName="TestNG">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="SUITE_NAME" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="METHOD_NAME" />
+ <option name="GROUP_NAME" />
+ <option name="TEST_OBJECT" value="CLASS" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="ANNOTATION_TYPE" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <option name="USE_DEFAULT_REPORTERS" value="false" />
+ <option name="PROPERTIES_FILE" />
+ <envs />
+ <properties />
+ <listeners />
+ <method />
+ </configuration>
+ <configuration default="true" type="Applet" factoryName="Applet">
+ <module name="" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="HTML_FILE_NAME" />
+ <option name="HTML_USED" value="false" />
+ <option name="WIDTH" value="400" />
+ <option name="HEIGHT" value="300" />
+ <option name="POLICY_FILE" value="$IDEA_HOME$/bin/appletviewer.policy" />
+ <option name="VM_PARAMETERS" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <method />
+ </configuration>
+ <configuration default="true" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="VM_PARAMETERS" />
+ <option name="PROGRAM_PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="" />
+ <envs />
+ <method />
+ </configuration>
+ <configuration default="true" type="JUnit" factoryName="JUnit">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="METHOD_NAME" />
+ <option name="TEST_OBJECT" value="class" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <envs />
+ <patterns />
+ <method />
+ </configuration>
+ <configuration default="true" type="FlashRunConfigurationType" factoryName="Flash App">
+ <option name="BCName" value="" />
+ <option name="IOSSimulatorSdkPath" value="" />
+ <option name="adlOptions" value="" />
+ <option name="airProgramParameters" value="" />
+ <option name="appDescriptorForEmulator" value="Android" />
+ <option name="debugTransport" value="USB" />
+ <option name="debuggerSdkRaw" value="BC SDK" />
+ <option name="emulator" value="NexusOne" />
+ <option name="emulatorAdlOptions" value="" />
+ <option name="fastPackaging" value="true" />
+ <option name="fullScreenHeight" value="0" />
+ <option name="fullScreenWidth" value="0" />
+ <option name="launchUrl" value="false" />
+ <option name="launcherParameters">
+ <LauncherParameters>
+ <option name="browserFamily" value="FIREFOX" />
+ <option name="launcherType" value="OSDefault" />
+ <option name="playerPath" value="/usr/bin/flashplayerdebugger" />
+ </LauncherParameters>
+ </option>
+ <option name="mobileRunTarget" value="Emulator" />
+ <option name="moduleName" value="" />
+ <option name="overriddenMainClass" value="" />
+ <option name="overriddenOutputFileName" value="" />
+ <option name="overrideMainClass" value="false" />
+ <option name="runTrusted" value="true" />
+ <option name="screenDpi" value="0" />
+ <option name="screenHeight" value="0" />
+ <option name="screenWidth" value="0" />
+ <option name="url" value="http://" />
+ <option name="usbDebugPort" value="7936" />
+ <method />
+ </configuration>
+ <configuration default="false" name="Main" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="xxx.Main" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="run-configurations" />
+ <envs />
+ <method />
+ </configuration>
+ <list size="3">
+ <item index="0" class="java.lang.String" itemvalue="Application.Main" />
+ <item index="1" class="java.lang.String" itemvalue="Application.shared" />
+ <item index="2" class="java.lang.String" itemvalue="JUnit.test" />
+ </list>
+ <configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
+ <Host>localhost</Host>
+ <Port>5050</Port>
+ </configuration>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/run-configurations-dir/run-configurations.iml b/jps/model-serialization/testData/run-configurations-dir/run-configurations.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations-dir/run-configurations.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/run-configurations/run-configurations.iml b/jps/model-serialization/testData/run-configurations/run-configurations.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations/run-configurations.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/run-configurations/run-configurations.ipr b/jps/model-serialization/testData/run-configurations/run-configurations.ipr
new file mode 100644
index 000000000000..93c6bd97232b
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations/run-configurations.ipr
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/run-configurations.iml" filepath="$PROJECT_DIR$/run-configurations.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+ <component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="shared" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="xxx.Main2" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="run-configurations" />
+ <envs />
+ <method />
+ </configuration>
+ <configuration default="false" name="test" type="JUnit" factoryName="JUnit">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="run-configurations" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" value="test.MyTest" />
+ <option name="METHOD_NAME" value="" />
+ <option name="TEST_OBJECT" value="class" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <envs />
+ <patterns />
+ <method />
+ </configuration>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/run-configurations/run-configurations.iws b/jps/model-serialization/testData/run-configurations/run-configurations.iws
new file mode 100644
index 000000000000..9a6aefa67f30
--- /dev/null
+++ b/jps/model-serialization/testData/run-configurations/run-configurations.iws
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunManager" selected="JUnit.test">
+ <configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
+ <module name="" />
+ <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m" />
+ <option name="PROGRAM_PARAMETERS" />
+ <method />
+ </configuration>
+ <configuration default="true" type="CapistranoRunConfigurationType" factoryName="Capistrano">
+ <module name="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="WORK DIR" VALUE="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="SHOULD_USE_SDK" VALUE="false" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="ALTERN_SDK_NAME" VALUE="" />
+ <CAPISTRANO_RUN_CONFIGURATION NAME="myPassParentEnvs" VALUE="true" />
+ <envs />
+ <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
+ <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
+ <COVERAGE_PATTERN ENABLED="true">
+ <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
+ </COVERAGE_PATTERN>
+ </EXTENSION>
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_TASK_NAME" VALUE="" />
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_TASK_ARGS" VALUE="" />
+ <CAPISTRANO_RUN_CONFIG_SETTINGS_ID NAME="CAPISTRANO_STAGE" VALUE="" />
+ <method />
+ </configuration>
+ <configuration default="true" type="Remote" factoryName="Remote">
+ <option name="USE_SOCKET_TRANSPORT" value="true" />
+ <option name="SERVER_MODE" value="false" />
+ <option name="SHMEM_ADDRESS" value="javadebug" />
+ <option name="HOST" value="localhost" />
+ <option name="PORT" value="5005" />
+ <method />
+ </configuration>
+ <configuration default="true" type="Applet" factoryName="Applet">
+ <module name="" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="HTML_FILE_NAME" />
+ <option name="HTML_USED" value="false" />
+ <option name="WIDTH" value="400" />
+ <option name="HEIGHT" value="300" />
+ <option name="POLICY_FILE" value="$IDEA_HOME$/bin/appletviewer.policy" />
+ <option name="VM_PARAMETERS" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <method />
+ </configuration>
+ <configuration default="true" type="TestNG" factoryName="TestNG">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="SUITE_NAME" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="METHOD_NAME" />
+ <option name="GROUP_NAME" />
+ <option name="TEST_OBJECT" value="CLASS" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="ANNOTATION_TYPE" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <option name="USE_DEFAULT_REPORTERS" value="false" />
+ <option name="PROPERTIES_FILE" />
+ <envs />
+ <properties />
+ <listeners />
+ <method />
+ </configuration>
+ <configuration default="true" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="VM_PARAMETERS" />
+ <option name="PROGRAM_PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="" />
+ <envs />
+ <method />
+ </configuration>
+ <configuration default="true" type="JUnit" factoryName="JUnit">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <module name="" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="METHOD_NAME" />
+ <option name="TEST_OBJECT" value="class" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="moduleWithDependencies" />
+ </option>
+ <envs />
+ <patterns />
+ <method />
+ </configuration>
+ <configuration default="true" type="FlashRunConfigurationType" factoryName="Flash App">
+ <option name="BCName" value="" />
+ <option name="IOSSimulatorSdkPath" value="" />
+ <option name="adlOptions" value="" />
+ <option name="airProgramParameters" value="" />
+ <option name="appDescriptorForEmulator" value="Android" />
+ <option name="debugTransport" value="USB" />
+ <option name="debuggerSdkRaw" value="BC SDK" />
+ <option name="emulator" value="NexusOne" />
+ <option name="emulatorAdlOptions" value="" />
+ <option name="fastPackaging" value="true" />
+ <option name="fullScreenHeight" value="0" />
+ <option name="fullScreenWidth" value="0" />
+ <option name="launchUrl" value="false" />
+ <option name="launcherParameters">
+ <LauncherParameters>
+ <option name="browserFamily" value="FIREFOX" />
+ <option name="launcherType" value="OSDefault" />
+ <option name="playerPath" value="/usr/bin/flashplayerdebugger" />
+ </LauncherParameters>
+ </option>
+ <option name="mobileRunTarget" value="Emulator" />
+ <option name="moduleName" value="" />
+ <option name="overriddenMainClass" value="" />
+ <option name="overriddenOutputFileName" value="" />
+ <option name="overrideMainClass" value="false" />
+ <option name="runTrusted" value="true" />
+ <option name="screenDpi" value="0" />
+ <option name="screenHeight" value="0" />
+ <option name="screenWidth" value="0" />
+ <option name="url" value="http://" />
+ <option name="usbDebugPort" value="7936" />
+ <method />
+ </configuration>
+ <configuration default="false" name="Main" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="xxx.Main" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="run-configurations" />
+ <envs />
+ <method />
+ </configuration>
+ <list size="2">
+ <item index="0" class="java.lang.String" itemvalue="Application.Main" />
+ <item index="1" class="java.lang.String" itemvalue="JUnit.test" />
+ </list>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/sampleProject/.idea/.name b/jps/model-serialization/testData/sampleProject/.idea/.name
new file mode 100644
index 000000000000..697c385c871b
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/.name
@@ -0,0 +1 @@
+sampleProjectName
diff --git a/jps/model-serialization/testData/sampleProject/.idea/artifacts/dir.xml b/jps/model-serialization/testData/sampleProject/.idea/artifacts/dir.xml
new file mode 100644
index 000000000000..bbaca161d1f9
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/artifacts/dir.xml
@@ -0,0 +1,17 @@
+<component name="ArtifactManager">
+ <artifact build-on-make="true" name="dir">
+ <output-path>$PROJECT_DIR$/out/artifacts/dir</output-path>
+ <root id="root">
+ <element id="archive" name="x.jar">
+ <element id="module-output" name="util" />
+ </element>
+ <element id="directory" name="lib">
+ <element id="library" level="module" name="log4j" module-name="util" />
+ <element id="library" level="project" name="junit" />
+ <element id="file-copy" path="$PROJECT_DIR$/main.iml" />
+ <element id="dir-copy" path="$PROJECT_DIR$/lib/junit-anno" />
+ <element id="extracted-dir" path="$PROJECT_DIR$/lib/junit.jar" path-in-jar="/junit/" />
+ </element>
+ </root>
+ </artifact>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/sampleProject/.idea/artifacts/jar.xml b/jps/model-serialization/testData/sampleProject/.idea/artifacts/jar.xml
new file mode 100644
index 000000000000..7e19ac521425
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/artifacts/jar.xml
@@ -0,0 +1,10 @@
+<component name="ArtifactManager">
+ <artifact type="jar" name="jar">
+ <output-path>$PROJECT_DIR$/out/artifacts/jar</output-path>
+ <root id="archive" name="jar.jar">
+ <element id="module-output" name="main" />
+ <element id="module-output" name="util" />
+ <element id="artifact" artifact-name="dir" />
+ </root>
+ </artifact>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/sampleProject/.idea/compiler.xml b/jps/model-serialization/testData/sampleProject/.idea/compiler.xml
new file mode 100644
index 000000000000..a1b41c52c724
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/compiler.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ <entry name="?*.ftl" />
+ </wildcardResourcePatterns>
+ <annotationProcessing enabled="false" useClasspath="true" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/sampleProject/.idea/encodings.xml b/jps/model-serialization/testData/sampleProject/.idea/encodings.xml
new file mode 100644
index 000000000000..e92ae351bfb0
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/encodings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="UTF-8">
+ <file url="file://$PROJECT_DIR$/util" charset="windows-1251" />
+ <file url="PROJECT" charset="UTF-8" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/sampleProject/.idea/libraries/jarDir.xml b/jps/model-serialization/testData/sampleProject/.idea/libraries/jarDir.xml
new file mode 100644
index 000000000000..b5b244c698e3
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/libraries/jarDir.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+ <library name="jarDir">
+ <CLASSES>
+ <root url="file://$PROJECT_DIR$/lib/jarDir" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$PROJECT_DIR$/lib/jarDir/src" />
+ </SOURCES>
+ <jarDirectory url="file://$PROJECT_DIR$/lib/jarDir" recursive="false" />
+ <jarDirectory url="file://$PROJECT_DIR$/lib/jarDir/src" recursive="false" type="SOURCES" />
+ </library>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/sampleProject/.idea/libraries/junit.xml b/jps/model-serialization/testData/sampleProject/.idea/libraries/junit.xml
new file mode 100644
index 000000000000..72885d1ec69f
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/libraries/junit.xml
@@ -0,0 +1,15 @@
+<component name="libraryTable">
+ <library name="junit">
+ <ANNOTATIONS>
+ <root url="file://$PROJECT_DIR$/lib/junit-anno" />
+ </ANNOTATIONS>
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/junit.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="file://$PROJECT_DIR$/lib/javadoc" />
+ <root url="http://javadoc" />
+ </JAVADOC>
+ <SOURCES />
+ </library>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/sampleProject/.idea/libraries/log4j.xml b/jps/model-serialization/testData/sampleProject/.idea/libraries/log4j.xml
new file mode 100644
index 000000000000..909eb84ce54e
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/libraries/log4j.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="log4j">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/log4j.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/lib/log4j.zip!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/jps/model-serialization/testData/sampleProject/.idea/misc.xml b/jps/model-serialization/testData/sampleProject/.idea/misc.xml
new file mode 100644
index 000000000000..78f096fb90ba
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/sampleProject/.idea/modules.xml b/jps/model-serialization/testData/sampleProject/.idea/modules.xml
new file mode 100644
index 000000000000..8024c0144276
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/.idea/modules.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/main.iml" filepath="$PROJECT_DIR$/main.iml" />
+ <module fileurl="file://$PROJECT_DIR$/util/util.iml" filepath="$PROJECT_DIR$/util/util.iml" />
+ <module fileurl="file://$PROJECT_DIR$/xxx/xxx.iml" filepath="$PROJECT_DIR$/xxx/xxx.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/sampleProject/main.iml b/jps/model-serialization/testData/sampleProject/main.iml
new file mode 100644
index 000000000000..598977a75f8d
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/main.iml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="log4j" level="project" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
+ <orderEntry type="library" exported="" name="jarDir" level="project" />
+ <orderEntry type="module" module-name="util" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/sampleProject/util/util.iml b/jps/model-serialization/testData/sampleProject/util/util.iml
new file mode 100644
index 000000000000..bde922eec436
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/util/util.iml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../out/production-util" />
+ <output-test url="file://$MODULE_DIR$/../out/test-util" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="xxx" />
+ <excludeFolder url="file://$MODULE_DIR$/exc" />
+ </content>
+ <orderEntry type="jdk" jdkName="1.5" jdkType="JavaSDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module-library" scope="TEST">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/junit.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="log4j">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/log4j.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../lib/log4j.zip!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <javadoc-paths>
+ <root url="file://$MODULE_DIR$/../lib/javadoc" />
+ </javadoc-paths>
+ <annotation-paths>
+ <root url="file://$MODULE_DIR$/../lib/anno" />
+ </annotation-paths>
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/sampleProject/xxx/xxx.iml b/jps/model-serialization/testData/sampleProject/xxx/xxx.iml
new file mode 100644
index 000000000000..36d6b2fa62ee
--- /dev/null
+++ b/jps/model-serialization/testData/sampleProject/xxx/xxx.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/output" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testSrc/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/jps/model-serialization/testSrc/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
new file mode 100644
index 000000000000..5d950b5e2031
--- /dev/null
+++ b/jps/model-serialization/testSrc/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
@@ -0,0 +1 @@
+org.jetbrains.jps.model.serialization.JpsTestSerializerExtension \ No newline at end of file
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/JpsEncodingConfigurationServiceTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/JpsEncodingConfigurationServiceTest.java
new file mode 100644
index 000000000000..b1f704a9d37b
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/JpsEncodingConfigurationServiceTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model;
+
+import org.jetbrains.jps.model.serialization.JpsSerializationTestCase;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class JpsEncodingConfigurationServiceTest extends JpsSerializationTestCase {
+ public void test() {
+ loadProject("/jps/model-serialization/testData/fileEncoding/fileEncoding.ipr");
+ JpsEncodingProjectConfiguration configuration = JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(myProject);
+ assertNotNull(configuration);
+ assertEncoding("windows-1251", "dir/a.txt", configuration);
+ assertEncoding("UTF-8", "dir/with-encoding.xml", configuration);
+ assertEncoding("windows-1251", "dir/without-encoding.xml", configuration);
+ assertEncoding("windows-1251", "dir/non-existent.xml", configuration);
+ }
+
+ private void assertEncoding(final String encoding, final String path, JpsEncodingProjectConfiguration configuration) {
+ assertEquals(encoding, configuration.getEncoding(new File(getAbsolutePath(path))));
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsArtifactSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsArtifactSerializationTest.java
new file mode 100644
index 000000000000..f03b784c2c53
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsArtifactSerializationTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.PlatformTestUtil;
+import org.jdom.Element;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import static org.jetbrains.jps.model.serialization.JpsProjectSerializationTest.SAMPLE_PROJECT_PATH;
+
+/**
+ * @author nik
+ */
+public class JpsArtifactSerializationTest extends JpsSerializationTestCase {
+ public void testLoadProject() {
+ loadProject(SAMPLE_PROJECT_PATH);
+ List<JpsArtifact> artifacts = getService().getSortedArtifacts(myProject);
+ assertEquals(2, artifacts.size());
+ assertEquals("dir", artifacts.get(0).getName());
+ assertEquals("jar", artifacts.get(1).getName());
+ }
+
+ public void testSaveProject() {
+ loadProject(SAMPLE_PROJECT_PATH);
+ File[] artifactFiles = new File(getTestDataFileAbsolutePath(SAMPLE_PROJECT_PATH + "/.idea/artifacts")).listFiles();
+ assertNotNull(artifactFiles);
+ for (File file : artifactFiles) {
+ JpsArtifact artifact = getService().createReference(FileUtil.getNameWithoutExtension(file)).asExternal(myModel).resolve();
+ assertNotNull(artifact);
+ doTestSaveArtifact(artifact, file);
+ }
+ }
+
+ private void doTestSaveArtifact(JpsArtifact artifact, File expectedFile) {
+ try {
+ Element actual = new Element("component").setAttribute("name", "ArtifactManager");
+ JpsArtifactSerializer.saveArtifact(artifact, actual);
+ JpsMacroExpander
+ expander = JpsProjectLoader.createProjectMacroExpander(Collections.<String, String>emptyMap(), new File(getTestDataFileAbsolutePath(SAMPLE_PROJECT_PATH)));
+ Element expected = JpsLoaderBase.loadRootElement(expectedFile, expander);
+ PlatformTestUtil.assertElementsEqual(expected, actual);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static JpsArtifactService getService() {
+ return JpsArtifactService.getInstance();
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsCompilerConfigurationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsCompilerConfigurationTest.java
new file mode 100644
index 000000000000..654f349a96a2
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsCompilerConfigurationTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+public class JpsCompilerConfigurationTest extends JpsSerializationTestCase {
+ public void testLoadFromIpr() {
+ doTest("jps/model-serialization/testData/compilerConfiguration/compilerConfiguration.ipr");
+ }
+
+ public void testLoadFromDirectory() {
+ doTest("jps/model-serialization/testData/compilerConfigurationDir");
+ }
+
+ private void doTest(final String path) {
+ loadProject(path);
+ JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(myProject);
+ assertNotNull(configuration);
+ assertFalse(configuration.isClearOutputDirectoryOnRebuild());
+ assertFalse(configuration.isAddNotNullAssertions());
+ ProcessorConfigProfile defaultProfile = configuration.getDefaultAnnotationProcessingProfile();
+ assertTrue(defaultProfile.isEnabled());
+ assertFalse(defaultProfile.isObtainProcessorsFromClasspath());
+ assertEquals(FileUtil.toSystemDependentName(JpsPathUtil.urlToPath(getUrl("src"))), defaultProfile.getProcessorPath());
+ assertEquals("b", defaultProfile.getProcessorOptions().get("a"));
+ assertEquals("d", defaultProfile.getProcessorOptions().get("c"));
+ assertEquals("gen", defaultProfile.getGeneratedSourcesDirectoryName(false));
+ JpsCompilerExcludes excludes = configuration.getCompilerExcludes();
+ assertFalse(isExcluded(excludes, "src/nonrec/x/Y.java"));
+ assertTrue(isExcluded(excludes, "src/nonrec/Y.java"));
+ assertTrue(isExcluded(excludes, "src/rec/x/Y.java"));
+ assertTrue(isExcluded(excludes, "src/rec/Y.java"));
+ assertTrue(isExcluded(excludes, "src/A.java"));
+ assertFalse(isExcluded(excludes, "src/B.java"));
+
+ JpsJavaCompilerOptions options = configuration.getCurrentCompilerOptions();
+ assertNotNull(options);
+ assertEquals(512, options.MAXIMUM_HEAP_SIZE);
+ assertFalse(options.DEBUGGING_INFO);
+ assertTrue(options.GENERATE_NO_WARNINGS);
+ assertEquals("-Xlint", options.ADDITIONAL_OPTIONS_STRING);
+ }
+
+ private boolean isExcluded(JpsCompilerExcludes excludes, final String path) {
+ return excludes.isExcluded(JpsPathUtil.urlToFile(getUrl(path)));
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsGlobalSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsGlobalSerializationTest.java
new file mode 100644
index 000000000000..98536ddde1a8
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsGlobalSerializationTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.testFramework.PlatformTestUtil;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsGlobalSerializationTest extends JpsSerializationTestCase {
+ private static final String OPTIONS_DIR = "jps/model-serialization/testData/config/options";
+
+ public void testLoadSdks() {
+ loadGlobalSettings(OPTIONS_DIR);
+ final List<JpsLibrary> libraries = myModel.getGlobal().getLibraryCollection().getLibraries();
+ assertEquals(3, libraries.size());
+ assertEquals("Gant", libraries.get(0).getName());
+ final JpsLibrary sdk1 = libraries.get(1);
+ assertEquals("1.5", sdk1.getName());
+ final JpsLibrary sdk2 = libraries.get(2);
+ assertEquals("1.6", sdk2.getName());
+ }
+
+ public void testSaveSdks() throws JDOMException, IOException {
+ loadGlobalSettings(OPTIONS_DIR);
+ Element actual = new Element("component").setAttribute("name", "ProjectJdkTable");
+ JpsSdkTableSerializer.saveSdks(myModel.getGlobal().getLibraryCollection(), actual);
+ File jdkTableFile = new File(getTestDataFileAbsolutePath(OPTIONS_DIR), "jdk.table.xml");
+ JpsMacroExpander expander = new JpsMacroExpander(getPathVariables());
+ Element expected = JDomSerializationUtil.findComponent(JpsLoaderBase.loadRootElement(jdkTableFile, expander), "ProjectJdkTable");
+ PlatformTestUtil.assertElementsEqual(expected, actual);
+ }
+
+ public void testLoadEncoding() {
+ loadGlobalSettings(OPTIONS_DIR);
+ assertEquals("windows-1251", JpsEncodingConfigurationService.getInstance().getGlobalEncoding(myModel.getGlobal()));
+ }
+
+ public void testLoadIgnoredFiles() {
+ loadGlobalSettings(OPTIONS_DIR);
+ assertEquals("CVS;.svn;", myModel.getGlobal().getFileTypesConfiguration().getIgnoredPatternString());
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java
new file mode 100644
index 000000000000..32719f02ef6d
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.PlatformTestUtil;
+import org.jdom.Element;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.module.*;
+import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsProjectSerializationTest extends JpsSerializationTestCase {
+ public static final String SAMPLE_PROJECT_PATH = "/jps/model-serialization/testData/sampleProject";
+
+ public void testLoadProject() {
+ loadProject(SAMPLE_PROJECT_PATH);
+ String baseDirPath = getTestDataFileAbsolutePath(SAMPLE_PROJECT_PATH);
+ assertTrue(FileUtil.filesEqual(new File(baseDirPath), JpsModelSerializationDataService.getBaseDirectory(myProject)));
+ assertEquals("sampleProjectName", myProject.getName());
+ List<JpsModule> modules = myProject.getModules();
+ assertEquals(3, modules.size());
+ JpsModule main = modules.get(0);
+ assertEquals("main", main.getName());
+ JpsModule util = modules.get(1);
+ assertEquals("util", util.getName());
+ JpsModule xxx = modules.get(2);
+ assertEquals("xxx", xxx.getName());
+
+ assertTrue(FileUtil.filesEqual(new File(baseDirPath, "util"), JpsModelSerializationDataService.getBaseDirectory(util)));
+
+ List<JpsLibrary> libraries = myProject.getLibraryCollection().getLibraries();
+ assertEquals(3, libraries.size());
+
+ List<JpsDependencyElement> dependencies = util.getDependenciesList().getDependencies();
+ assertEquals(4, dependencies.size());
+ JpsSdkDependency sdkDependency = assertInstanceOf(dependencies.get(0), JpsSdkDependency.class);
+ assertSame(JpsJavaSdkType.INSTANCE, sdkDependency.getSdkType());
+ JpsSdkReference<?> reference = sdkDependency.getSdkReference();
+ assertNotNull(reference);
+ assertEquals("1.5", reference.getSdkName());
+ assertInstanceOf(dependencies.get(1), JpsModuleSourceDependency.class);
+ assertInstanceOf(dependencies.get(2), JpsLibraryDependency.class);
+ assertInstanceOf(dependencies.get(3), JpsLibraryDependency.class);
+
+ JpsSdkDependency inheritedSdkDependency = assertInstanceOf(main.getDependenciesList().getDependencies().get(0), JpsSdkDependency.class);
+ JpsSdkReference<?> projectSdkReference = inheritedSdkDependency.getSdkReference();
+ assertNotNull(projectSdkReference);
+ assertEquals("1.6", projectSdkReference.getSdkName());
+
+ assertEquals(getUrl("xxx/output"), JpsJavaExtensionService.getInstance().getOutputUrl(xxx, true));
+ assertEquals(getUrl("xxx/output"), JpsJavaExtensionService.getInstance().getOutputUrl(xxx, false));
+ }
+
+ public void testFileBasedProjectNameAndBaseDir() {
+ String relativePath = "/jps/model-serialization/testData/run-configurations/run-configurations.ipr";
+ String absolutePath = getTestDataFileAbsolutePath(relativePath);
+ loadProject(relativePath);
+ assertEquals("run-configurations", myProject.getName());
+ assertTrue(FileUtil.filesEqual(new File(absolutePath).getParentFile(), JpsModelSerializationDataService.getBaseDirectory(myProject)));
+ }
+
+ public void testDirectoryBasedProjectName() {
+ loadProject("/jps/model-serialization/testData/run-configurations-dir");
+ assertEquals("run-configurations-dir", myProject.getName());
+ }
+
+ public void testImlUnderDotIdea() {
+ loadProject("/jps/model-serialization/testData/imlUnderDotIdea");
+ JpsModule module = assertOneElement(myProject.getModules());
+ JpsModuleSourceRoot root = assertOneElement(module.getSourceRoots());
+ assertEquals(getUrl("src"), root.getUrl());
+ }
+
+ public void testProjectSdkWithoutType() {
+ loadProject("/jps/model-serialization/testData/projectSdkWithoutType/projectSdkWithoutType.ipr");
+ JpsSdkReference<JpsDummyElement> reference = myProject.getSdkReferencesTable().getSdkReference(JpsJavaSdkType.INSTANCE);
+ assertNotNull(reference);
+ assertEquals("1.6", reference.getSdkName());
+ }
+
+ public void testLoadEncoding() {
+ loadProject(SAMPLE_PROJECT_PATH);
+ JpsEncodingConfigurationService service = JpsEncodingConfigurationService.getInstance();
+ assertEquals("UTF-8", service.getProjectEncoding(myModel));
+ JpsEncodingProjectConfiguration configuration = service.getEncodingConfiguration(myProject);
+ assertNotNull(configuration);
+ assertEquals("UTF-8", configuration.getProjectEncoding());
+ assertEquals("windows-1251", configuration.getEncoding(new File(getAbsolutePath("util"))));
+ assertEquals("windows-1251", configuration.getEncoding(new File(getAbsolutePath("util/foo/bar/file.txt"))));
+ assertEquals("UTF-8", configuration.getEncoding(new File(getAbsolutePath("other"))));
+ }
+
+ public void testSaveProject() {
+ loadProject(SAMPLE_PROJECT_PATH);
+ List<JpsModule> modules = myProject.getModules();
+ doTestSaveModule(modules.get(0), "main.iml");
+ doTestSaveModule(modules.get(1), "util/util.iml");
+ //tod[nik] remember that test output root wasn't specified and doesn't save it to avoid unnecessary modifications of iml files
+ //doTestSaveModule(modules.get(2), "xxx/xxx.iml");
+
+ File[] libs = getFileInSampleProject(".idea/libraries").listFiles();
+ assertNotNull(libs);
+ for (File libFile : libs) {
+ String libName = FileUtil.getNameWithoutExtension(libFile);
+ JpsLibrary library = myProject.getLibraryCollection().findLibrary(libName);
+ assertNotNull(libName, library);
+ doTestSaveLibrary(libFile, libName, library);
+ }
+ }
+
+ private void doTestSaveLibrary(File libFile, String libName, JpsLibrary library) {
+ try {
+ Element actual = new Element("library");
+ JpsLibraryTableSerializer.saveLibrary(library, actual, libName);
+ JpsMacroExpander
+ macroExpander = JpsProjectLoader.createProjectMacroExpander(Collections.<String, String>emptyMap(), getFileInSampleProject(""));
+ Element rootElement = JpsLoaderBase.loadRootElement(libFile, macroExpander);
+ Element expected = rootElement.getChild("library");
+ PlatformTestUtil.assertElementsEqual(expected, actual);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void doTestSaveModule(JpsModule module, final String moduleFilePath) {
+ try {
+ Element actual = JDomSerializationUtil.createComponentElement("NewModuleRootManager");
+ JpsModuleRootModelSerializer.saveRootModel(module, actual);
+ File imlFile = getFileInSampleProject(moduleFilePath);
+ Element rootElement = loadModuleRootTag(imlFile);
+ Element expected = JDomSerializationUtil.findComponent(rootElement, "NewModuleRootManager");
+ PlatformTestUtil.assertElementsEqual(expected, actual);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public File getFileInSampleProject(String relativePath) {
+ return new File(getTestDataFileAbsolutePath(SAMPLE_PROJECT_PATH + "/" + relativePath));
+ }
+
+ public void testLoadIdeaProject() {
+ long start = System.currentTimeMillis();
+ loadProjectByAbsolutePath(PathManager.getHomePath());
+ assertTrue(myProject.getModules().size() > 0);
+ System.out.println("JpsProjectSerializationTest: " + myProject.getModules().size() + " modules, " + myProject.getLibraryCollection().getLibraries().size() + " libraries and " +
+ JpsArtifactService.getInstance().getArtifacts(myProject).size() + " artifacts loaded in " + (System.currentTimeMillis() - start) + "ms");
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsRunConfigurationsSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsRunConfigurationsSerializationTest.java
new file mode 100644
index 000000000000..44cc637ab2f4
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsRunConfigurationsSerializationTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationProperties;
+import org.jetbrains.jps.model.java.runConfiguration.JpsApplicationRunConfigurationType;
+import org.jetbrains.jps.model.runConfiguration.JpsTypedRunConfiguration;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsRunConfigurationsSerializationTest extends JpsSerializationTestCase {
+ public void testLoadIpr() {
+ doTest("jps/model-serialization/testData/run-configurations/run-configurations.ipr");
+ }
+
+ public void testLoadDirectoryBased() {
+ doTest("jps/model-serialization/testData/run-configurations-dir");
+ }
+
+ private void doTest(final String relativePath) {
+ loadProject(relativePath);
+ List<JpsTypedRunConfiguration<JpsApplicationRunConfigurationProperties>>
+ configurations = ContainerUtil.newArrayList(myProject.getRunConfigurations(JpsApplicationRunConfigurationType.INSTANCE));
+ assertEquals(2, configurations.size());
+
+ JpsTypedRunConfiguration<JpsApplicationRunConfigurationProperties> shared = configurations.get(0);
+ assertEquals("shared", shared.getName());
+ assertEquals("xxx.Main2", shared.getProperties().getMainClass());
+
+ JpsTypedRunConfiguration<JpsApplicationRunConfigurationProperties> main = configurations.get(1);
+ assertEquals("Main", main.getName());
+ assertEquals("xxx.Main", main.getProperties().getMainClass());
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsSerializationTestCase.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsSerializationTestCase.java
new file mode 100644
index 000000000000..ccb003510295
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsSerializationTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import com.intellij.application.options.PathMacrosImpl;
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.util.PathUtil;
+import com.intellij.util.SystemProperties;
+import org.jdom.Element;
+import org.jetbrains.jps.model.JpsModelTestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public abstract class JpsSerializationTestCase extends JpsModelTestCase {
+ private String myProjectHomePath;
+
+ protected void loadProject(final String relativePath) {
+ loadProjectByAbsolutePath(getTestDataFileAbsolutePath(relativePath));
+ }
+
+ protected void loadProjectByAbsolutePath(String path) {
+ myProjectHomePath = FileUtilRt.toSystemIndependentName(path);
+ if (myProjectHomePath.endsWith(".ipr")) {
+ myProjectHomePath = PathUtil.getParentPath(myProjectHomePath);
+ }
+ try {
+ JpsProjectLoader.loadProject(myProject, getPathVariables(), path);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected String getUrl(String relativePath) {
+ return VfsUtilCore.pathToUrl(getAbsolutePath(relativePath));
+ }
+
+ protected String getAbsolutePath(String relativePath) {
+ return myProjectHomePath + "/" + relativePath;
+ }
+
+ protected void loadGlobalSettings(final String optionsDir) {
+ try {
+ String optionsPath = getTestDataFileAbsolutePath(optionsDir);
+ Map<String,String> pathVariables = getPathVariables();
+ JpsGlobalLoader.loadGlobalSettings(myModel.getGlobal(), pathVariables, optionsPath);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected Map<String, String> getPathVariables() {
+ Map<String, String> variables = new HashMap<String, String>();
+ variables.put(PathMacrosImpl.APPLICATION_HOME_MACRO_NAME, PathManagerEx.getHomePath(getClass()));
+ variables.put(PathMacrosImpl.USER_HOME_MACRO_NAME, SystemProperties.getUserHome());
+ return variables;
+ }
+
+ protected String getTestDataFileAbsolutePath(String relativePath) {
+ return PathManagerEx.findFileUnderProjectHome(relativePath, getClass()).getAbsolutePath();
+ }
+
+ protected static Element loadModuleRootTag(File imlFile) {
+ JpsMacroExpander expander = JpsProjectLoader.createModuleMacroExpander(Collections.<String, String>emptyMap(), imlFile);
+ return JpsLoaderBase.loadRootElement(imlFile, expander);
+ }
+}
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsTestSerializerExtension.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsTestSerializerExtension.java
new file mode 100644
index 000000000000..e201a22e022c
--- /dev/null
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsTestSerializerExtension.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.model.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.serialization.java.JpsApplicationRunConfigurationSerializer;
+import org.jetbrains.jps.model.serialization.runConfigurations.JpsRunConfigurationPropertiesSerializer;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JpsTestSerializerExtension extends JpsModelSerializerExtension {
+ @NotNull
+ @Override
+ public List<? extends JpsRunConfigurationPropertiesSerializer<?>> getRunConfigurationPropertiesSerializers() {
+ return Collections.singletonList(new JpsApplicationRunConfigurationSerializer());
+ }
+}
diff --git a/jps/standalone-builder/jps-standalone-builder.iml b/jps/standalone-builder/jps-standalone-builder.iml
new file mode 100644
index 000000000000..186ddc1271c6
--- /dev/null
+++ b/jps/standalone-builder/jps-standalone-builder.iml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Groovy" level="project" />
+ <orderEntry type="module" module-name="jps-builders" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="module-library" scope="PROVIDED">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/gant-1.9.5_groovy-1.7.10.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="cli-parser" level="project" />
+ <orderEntry type="library" name="Ant" level="project" />
+ <orderEntry type="module" module-name="jps-model-serialization" />
+ </component>
+</module>
+
diff --git a/jps/standalone-builder/src/jps.gdsl b/jps/standalone-builder/src/jps.gdsl
new file mode 100644
index 000000000000..5299b3ccf7bf
--- /dev/null
+++ b/jps/standalone-builder/src/jps.gdsl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+def ctx = context(scope: scriptScope(), filetypes : ["gant"])
+
+contributor ([ctx], {
+ property name:"project", type:"org.jetbrains.jps.model.JpsProject"
+ property name:"global", type:"org.jetbrains.jps.model.JpsGlobal"
+ property name:"projectBuilder", type:"org.jetbrains.jps.gant.JpsGantProjectBuilder"
+ method name:"jdk", type:"void", params:[name:"String", jdkPath:"String"]
+ method name:"jdk", type:"void", params:[name:"String", jdkPath:"String", initializer:{}]
+
+ method name:"layout", type:"org.jetbrains.jps.gant.LayoutInfo", params: [name:"String", layout:{}]
+ method name:"module", type:"void", params: [name:"String"]
+ method name:"module", type:"void", params: [name:"String", layout:{}]
+ ["jar", "dir", "zip"].each { methodName ->
+ method name:methodName, type:"void", params: [name:"String", layout:{}]
+ }
+})
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/LayoutInfo.java b/jps/standalone-builder/src/org/jetbrains/jps/LayoutInfo.java
new file mode 100644
index 000000000000..673a5abe43e6
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/LayoutInfo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+//todo[nik] inline this class later
+public class LayoutInfo {
+ private Set<String> myUsedModules = new HashSet<String>();
+
+ public Set<String> getUsedModules() {
+ return myUsedModules;
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/build/GroovyModelInitializer.java b/jps/standalone-builder/src/org/jetbrains/jps/build/GroovyModelInitializer.java
new file mode 100644
index 000000000000..fe40e661e0d0
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/build/GroovyModelInitializer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.build;
+
+import com.intellij.util.ParameterizedRunnable;
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author nik
+ */
+public class GroovyModelInitializer implements ParameterizedRunnable<JpsModel> {
+ private File myScriptFile;
+
+ public GroovyModelInitializer(File scriptFile) {
+ myScriptFile = scriptFile;
+ }
+
+ @Override
+ public void run(JpsModel model) {
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("project", model.getProject());
+ variables.put("global", model.getGlobal());
+ try {
+ new GroovyShell(new Binding(variables)).evaluate(myScriptFile);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java
new file mode 100644
index 000000000000..1f6e04089a6d
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.build;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ParameterizedRunnable;
+import com.sampullara.cli.Args;
+import com.sampullara.cli.Argument;
+import org.jetbrains.jps.api.BuildType;
+import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.cmdline.BuildRunner;
+import org.jetbrains.jps.cmdline.JpsModelLoader;
+import org.jetbrains.jps.cmdline.JpsModelLoaderImpl;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.MessageHandler;
+import org.jetbrains.jps.incremental.Utils;
+import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType;
+import org.jetbrains.jps.incremental.fs.BuildFSState;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.model.JpsModel;
+
+import java.io.File;
+import java.util.*;
+
+import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
+
+/**
+ * @author nik
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"})
+public class Standalone {
+ @Argument(value = "config", prefix = "--", description = "Path to directory containing global options (idea.config.path)")
+ public String configPath;
+
+ @Argument(value = "script", prefix = "--", description = "Path to Groovy script which will be used to initialize global options")
+ public String initializationScriptPath;
+
+ @Argument(value = "modules", prefix = "--", delimiter = ",", description = "Comma-separated list of modules to compile")
+ public String[] modules = ArrayUtil.EMPTY_STRING_ARRAY;
+
+ @Argument(value = "artifacts", prefix = "--", delimiter = ",", description = "Comma-separated list of artifacts to build")
+ public String[] artifacts = ArrayUtil.EMPTY_STRING_ARRAY;
+
+ @Argument(value = "i", description = "Build incrementally")
+ public boolean incremental;
+
+ public static void main(String[] args) {
+ Standalone instance = new Standalone();
+ List<String> projectPaths;
+ try {
+ projectPaths = Args.parse(instance, args);
+ }
+ catch (Exception e) {
+ printUsageAndExit();
+ return;
+ }
+
+ if (projectPaths.isEmpty()) {
+ System.out.println("Path to project is not specified");
+ printUsageAndExit();
+ }
+ if (projectPaths.size() > 1) {
+ System.out.println("Only one project can be specified");
+ printUsageAndExit();
+ }
+
+
+
+ instance.loadAndRunBuild(projectPaths.get(0));
+ System.exit(0);
+ }
+
+ private static void printUsageAndExit() {
+ Args.usage(System.err, new Standalone());
+ System.exit(0);
+ }
+
+ public void loadAndRunBuild(final String projectPath) {
+ String globalOptionsPath = null;
+ if (configPath != null) {
+ File optionsDir = new File(configPath, "options");
+ if (!optionsDir.isDirectory()) {
+ System.err.println("'" + configPath + "' is not valid config path: " + optionsDir.getAbsolutePath() + " not found");
+ return;
+ }
+ globalOptionsPath = optionsDir.getAbsolutePath();
+ }
+
+ ParameterizedRunnable<JpsModel> initializer = null;
+ String scriptPath = initializationScriptPath;
+ if (scriptPath != null) {
+ File scriptFile = new File(scriptPath);
+ if (!scriptFile.isFile()) {
+ System.err.println("Script '" + scriptPath + "' not found");
+ return;
+ }
+ initializer = new GroovyModelInitializer(scriptFile);
+ }
+
+ Map<String, String> pathVars = new HashMap<String, String>();
+ pathVars.put("USER_HOME", System.getProperty("user.home"));
+ JpsModelLoaderImpl loader = new JpsModelLoaderImpl(projectPath, globalOptionsPath, pathVars, initializer);
+ BuildType buildType = incremental ? BuildType.MAKE : BuildType.PROJECT_REBUILD;
+ Set<String> modulesSet = new HashSet<String>(Arrays.asList(modules));
+ List<String> artifactsList = Arrays.asList(artifacts);
+ File dataStorageRoot = Utils.getDataStorageRoot(projectPath);
+ if (dataStorageRoot == null) {
+ System.err.println("Error: Cannot determine build data storage root for project " + projectPath);
+ return;
+ }
+
+ long start = System.currentTimeMillis();
+ try {
+ runBuild(loader, dataStorageRoot, buildType, modulesSet, artifactsList, true, new ConsoleMessageHandler());
+ }
+ catch (Throwable t) {
+ System.err.println("Internal error: " + t.getMessage());
+ t.printStackTrace();
+ }
+ System.out.println("Build finished in " + Utils.formatDuration(System.currentTimeMillis() - start));
+ }
+
+ public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, BuildType buildType, Set<String> modulesSet,
+ List<String> artifactsList, final boolean includeTests, final MessageHandler messageHandler) throws Exception {
+ List<TargetTypeBuildScope> scopes = new ArrayList<TargetTypeBuildScope>();
+ for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
+ if (includeTests || !type.isTests()) {
+ TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder().setTypeId(type.getTypeId());
+ if (modulesSet.isEmpty()) {
+ builder.setAllTargets(true);
+ }
+ else {
+ builder.addAllTargetId(modulesSet);
+ }
+ scopes.add(builder.build());
+ }
+ }
+ if (!artifactsList.isEmpty()) {
+ scopes.add(TargetTypeBuildScope.newBuilder().setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId()).addAllTargetId(artifactsList).build());
+ }
+ final BuildRunner buildRunner = new BuildRunner(loader, scopes, Collections.<String>emptyList(), Collections.<String, String>emptyMap());
+ ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true));
+ try {
+ buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, buildType);
+ }
+ finally {
+ descriptor.release();
+ }
+ }
+
+ private static class ConsoleMessageHandler implements MessageHandler {
+ @Override
+ public void processMessage(BuildMessage msg) {
+ String messageText = msg.getMessageText();
+ if (messageText.isEmpty()) return;
+ if (msg.getKind() == BuildMessage.Kind.ERROR) {
+ System.err.println("Error: " + messageText);
+ }
+ else if (msg.getKind() != BuildMessage.Kind.PROGRESS || !messageText.startsWith("Compiled") && !messageText.startsWith("Copying")) {
+ System.out.println(messageText);
+ }
+ }
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/BuildInfoPrinter.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/BuildInfoPrinter.java
new file mode 100644
index 000000000000..43eee91648be
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/BuildInfoPrinter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant;
+
+/**
+ * @author nik
+ */
+public interface BuildInfoPrinter {
+
+ void printProgressMessage(JpsGantProjectBuilder project, String message);
+
+ void printCompilationErrors(JpsGantProjectBuilder project, String compilerName, String messages);
+
+ void printCompilationFinish(JpsGantProjectBuilder project, String compilerName);
+
+ void printCompilationStart(JpsGantProjectBuilder project, String compilerName);
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java
new file mode 100644
index 000000000000..cd57ade929eb
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant;
+
+/**
+ * @author nik
+ */
+public class DefaultBuildInfoPrinter implements BuildInfoPrinter {
+ @Override
+ public void printProgressMessage(JpsGantProjectBuilder project, String message) {
+ project.info(message);
+ }
+
+ @Override
+ public void printCompilationErrors(JpsGantProjectBuilder project, String compilerName, String messages) {
+ project.error(messages);
+ }
+
+ @Override
+ public void printCompilationFinish(JpsGantProjectBuilder project, String compilerName) {
+ }
+
+ @Override
+ public void printCompilationStart(JpsGantProjectBuilder project, String compilerName) {
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java
new file mode 100644
index 000000000000..a5f4f35f6405
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant;
+
+import com.intellij.openapi.diagnostic.DefaultLogger;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.api.BuildType;
+import org.jetbrains.jps.build.Standalone;
+import org.jetbrains.jps.cmdline.JpsModelLoader;
+import org.jetbrains.jps.incremental.MessageHandler;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.java.JpsJavaClasspathKind;
+import org.jetbrains.jps.model.java.JpsJavaDependenciesEnumerator;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class JpsGantProjectBuilder {
+ private final Project myProject;
+ private final JpsModel myModel;
+ private boolean myCompressJars;
+ private File myDataStorageRoot;
+ private JpsModelLoader myModelLoader;
+ private boolean myDryRun;
+ private BuildInfoPrinter myBuildInfoPrinter = new DefaultBuildInfoPrinter();
+
+ public JpsGantProjectBuilder(Project project, JpsModel model) {
+ myProject = project;
+ myModel = model;
+ myModelLoader = new JpsModelLoader() {
+ @Override
+ public JpsModel loadModel() {
+ return myModel;
+ }
+ };
+ }
+
+ public void setDryRun(boolean dryRun) {
+ myDryRun = dryRun;
+ }
+
+ public void setTargetFolder(String targetFolder) {
+ String url = "file://" + FileUtil.toSystemIndependentName(targetFolder);
+ JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myModel.getProject()).setOutputUrl(url);
+ }
+
+ public boolean isCompressJars() {
+ return myCompressJars;
+ }
+
+ public void setCompressJars(boolean compressJars) {
+ myCompressJars = compressJars;
+ }
+
+ public void setBuildInfoPrinter(BuildInfoPrinter printer) {
+ myBuildInfoPrinter = printer;
+ }
+
+ public void setUseInProcessJavac(boolean value) {
+ //doesn't make sense for new builders
+ }
+
+ public void setArrangeModuleCyclesOutputs(boolean value) {
+ //doesn't make sense for new builders
+ }
+
+ public void error(String message) {
+ throw new BuildException(message);
+ }
+
+ public void error(Throwable t) {
+ throw new BuildException(t);
+ }
+
+ public void warning(String message) {
+ myProject.log(message, Project.MSG_WARN);
+ }
+
+ public void info(String message) {
+ myProject.log(message, Project.MSG_INFO);
+ }
+
+ public void stage(String message) {
+ myBuildInfoPrinter.printProgressMessage(this, message);
+ }
+
+ public File getDataStorageRoot() {
+ return myDataStorageRoot;
+ }
+
+ public void setDataStorageRoot(File dataStorageRoot) {
+ myDataStorageRoot = dataStorageRoot;
+ }
+
+ public void cleanOutput() {
+ if (myDryRun) {
+ info("Cleaning skipped as we're running dry");
+ return;
+ }
+
+ for (JpsModule module : myModel.getProject().getModules()) {
+ for (boolean test : new boolean[]{false, true}) {
+ File output = JpsJavaExtensionService.getInstance().getOutputDirectory(module, test);
+ if (output != null) {
+ FileUtil.delete(output);
+ }
+ }
+ }
+ }
+
+ public void makeModule(JpsModule module) {
+ runBuild(getModuleDependencies(module, false), false);
+ }
+
+ public void makeModuleTests(JpsModule module) {
+ runBuild(getModuleDependencies(module, true), true);
+ }
+
+ public void buildAll() {
+ runBuild(Collections.<String>emptySet(), true);
+ }
+
+ public void buildProduction() {
+ runBuild(Collections.<String>emptySet(), false);
+ }
+
+ public void exportModuleOutputProperties() {
+ for (JpsModule module : myModel.getProject().getModules()) {
+ for (boolean test : new boolean[]{true, false}) {
+ myProject.setProperty("module." + module.getName() + ".output." + (test ? "test" : "main"), getModuleOutput(module, test));
+ }
+ }
+
+ }
+
+ private static Set<String> getModuleDependencies(JpsModule module, boolean includeTests) {
+ Set<JpsModule> modules = JpsJavaExtensionService.dependencies(module).recursively().includedIn(JpsJavaClasspathKind.compile(includeTests)).getModules();
+ Set<String> names = new HashSet<String>();
+ for (JpsModule depModule : modules) {
+ names.add(depModule.getName());
+ }
+ return names;
+ }
+
+ private void runBuild(final Set<String> modulesSet, boolean includeTests) {
+ if (!myDryRun) {
+ final AntMessageHandler messageHandler = new AntMessageHandler();
+ Logger.setFactory(new AntLoggerFactory(messageHandler));
+ info("Starting build: modules = " + modulesSet + ", caches are saved to " + myDataStorageRoot.getAbsolutePath());
+ try {
+ Standalone.runBuild(myModelLoader, myDataStorageRoot, BuildType.PROJECT_REBUILD, modulesSet, Collections.<String>emptyList(),
+ includeTests, messageHandler);
+ }
+ catch (Throwable e) {
+ error(e);
+ }
+ }
+ else {
+ info("Building skipped as we're running dry");
+ }
+ }
+
+ public String moduleOutput(JpsModule module) {
+ return getModuleOutput(module, false);
+ }
+
+ public String moduleTestsOutput(JpsModule module) {
+ return getModuleOutput(module, true);
+ }
+
+ public String getModuleOutput(JpsModule module, boolean forTests) {
+ File directory = JpsJavaExtensionService.getInstance().getOutputDirectory(module, forTests);
+ return directory != null ? directory.getAbsolutePath() : null;
+ }
+
+ public List<String> moduleRuntimeClasspath(JpsModule module, boolean forTests) {
+ JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(module).recursively().includedIn(JpsJavaClasspathKind.runtime(forTests));
+ Collection<File> roots = enumerator.classes().getRoots();
+ List<String> result = new ArrayList<String>();
+ for (File root : roots) {
+ result.add(root.getAbsolutePath());
+ }
+ return result;
+ }
+
+ private class AntMessageHandler implements MessageHandler {
+ @Override
+ public void processMessage(BuildMessage msg) {
+ BuildMessage.Kind kind = msg.getKind();
+ String text = msg.getMessageText();
+ switch (kind) {
+ case ERROR:
+ String compilerName = msg instanceof CompilerMessage ? ((CompilerMessage)msg).getCompilerName() : "";
+ myBuildInfoPrinter.printCompilationErrors(JpsGantProjectBuilder.this, compilerName, text);
+ break;
+ case WARNING:
+ warning(text);
+ break;
+ case INFO:
+ if (!text.isEmpty()) {
+ info(text);
+ }
+ break;
+ case PROGRESS:
+ myBuildInfoPrinter.printProgressMessage(JpsGantProjectBuilder.this, text);
+ break;
+ }
+ }
+ }
+
+ private class AntLoggerFactory implements Logger.Factory {
+ private static final String COMPILER_NAME = "build runner";
+
+ private final AntMessageHandler myMessageHandler;
+
+ public AntLoggerFactory(AntMessageHandler messageHandler) {
+ myMessageHandler = messageHandler;
+ }
+
+ @Override
+ public Logger getLoggerInstance(String category) {
+ return new DefaultLogger(category) {
+ @Override
+ public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
+ if (t != null) {
+ myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, t));
+ }
+ else {
+ myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, message));
+ }
+ }
+
+ @Override
+ public void warn(@NonNls String message, @Nullable Throwable t) {
+ myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.WARNING, message));
+ }
+ };
+ }
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy
new file mode 100644
index 000000000000..79d6d4a6063d
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant
+import org.codehaus.gant.GantBinding
+import org.jetbrains.jps.incremental.Utils
+import org.jetbrains.jps.model.JpsElementFactory
+import org.jetbrains.jps.model.JpsGlobal
+import org.jetbrains.jps.model.JpsModel
+import org.jetbrains.jps.model.JpsProject
+import org.jetbrains.jps.model.java.JpsJavaExtensionService
+import org.jetbrains.jps.model.library.JpsOrderRootType
+import org.jetbrains.jps.model.serialization.JpsProjectLoader
+/**
+ * @author nik
+ */
+final class JpsGantTool {
+ JpsGantTool(GantBinding binding) {
+ JpsModel model = JpsElementFactory.getInstance().createModel();
+ JpsProject project = model.project
+ binding.setVariable("project", project)
+ binding.setVariable("global", model.global)
+ def builder = new JpsGantProjectBuilder(binding.ant.project, model)
+ binding.setVariable("projectBuilder", builder)
+ binding.setVariable("loadProjectFromPath", {String path ->
+ loadProject(path, model, builder);
+ })
+
+ binding.setVariable("jdk", {Object[] args ->
+ if (!(args.length in [2,3])) {
+ builder.error("expected 2 to 3 parameters for jdk() but ${args.length} found")
+ }
+ Closure initializer = args.length > 2 ? (Closure)args[2] : {}
+ return createJavaSdk(model.global, (String)args[0], (String)args[1], initializer)
+ })
+
+ binding.setVariable("layout", {String dir, Closure body ->
+ def layoutInfo = new LayoutInfo()
+
+ ["module", "moduleTests", "zip", "dir"].each {tag ->
+ binding.setVariable(tag, {Object[] args ->
+ if (args.length == 1) {
+ binding.ant."$tag"(name: args[0])
+ }
+ else if (args.length == 2) {
+ binding.ant."$tag"(name: args[0], args[1])
+ }
+ else {
+ builder.error("unexpected number of parameters for $tag")
+ }
+ if (tag == "module") {
+ layoutInfo.usedModules << args[0].toString()
+ }
+ })
+ }
+ binding.setVariable("jar", {Object[] args ->
+ if (args.length == 2) {
+ def param0 = args[0]
+ String name;
+ String duplicate = null;
+ if (param0 instanceof Map) {
+ name = param0.name;
+ duplicate = param0.duplicate;
+ }
+ else {
+ name = (String)param0;
+ }
+ if (duplicate == null) {
+ duplicate = "fail"
+ }
+ binding.ant.jar(name: name, compress: builder.compressJars, duplicate: duplicate, args[1])
+ }
+ else {
+ builder.error("unexpected number of parameters for 'jar' task: $args.length")
+ }
+ })
+
+ def meta = new Expando()
+ body.delegate = meta
+ binding.ant.layout(toDir: dir, body)
+ return layoutInfo
+ })
+
+ binding.ant.taskdef(name: "layout", classname: "jetbrains.antlayout.tasks.LayoutTask")
+ }
+
+ private void loadProject(String path, JpsModel model, JpsGantProjectBuilder builder) {
+ JpsProjectLoader.loadProject(model.project, [:], path)
+ builder.exportModuleOutputProperties();
+ if (builder.getDataStorageRoot() == null) {
+ builder.setDataStorageRoot(Utils.getDataStorageRoot(path))
+ }
+ builder.info("Loaded project " + path + ": " + model.getProject().getModules().size() + " modules, " + model.getProject().getLibraryCollection().getLibraries().size() + " libraries")
+ }
+
+ private void createJavaSdk(JpsGlobal global, String name, String homePath, Closure initializer) {
+ def sdk = JpsJavaExtensionService.getInstance().addJavaSdk(global, name, homePath)
+ def meta = new Expando()
+ meta.classpath = {String path ->
+ sdk.addRoot(new File(path), JpsOrderRootType.COMPILED)
+ }
+ initializer.delegate = meta
+ initializer.call()
+ }
+
+ public static String guessHome(Script script) {
+ File home = new File(script["gant.file"].substring("file:".length()))
+
+ while (home != null) {
+ if (home.isDirectory()) {
+ if (new File(home, ".idea").exists()) return home.getCanonicalPath()
+ }
+
+ home = home.getParentFile()
+ }
+
+ return null
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/LayoutInfo.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/LayoutInfo.java
new file mode 100644
index 000000000000..dc4551fa3ffd
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/LayoutInfo.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant;
+
+/**
+ * @author nik
+ */
+public class LayoutInfo extends org.jetbrains.jps.LayoutInfo {
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/TeamCityBuildInfoPrinter.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/TeamCityBuildInfoPrinter.java
new file mode 100644
index 000000000000..415461e2041d
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/TeamCityBuildInfoPrinter.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gant;
+
+/**
+ * @author nik
+ */
+public class TeamCityBuildInfoPrinter implements BuildInfoPrinter {
+ private static char escapedChar(char c) {
+ switch (c) {
+ case '\n': return 'n';
+ case '\r': return 'r';
+ case '\u0085': return 'x'; // next-line character
+ case '\u2028': return 'l'; // line-separator character
+ case '\u2029': return 'p'; // paragraph-separator character
+ case '|': return '|';
+ case '\'': return '\'';
+ case '[': return '[';
+ case ']': return ']';
+ }
+
+ return 0;
+ }
+
+ private static String escape(String text) {
+ StringBuilder escaped = new StringBuilder();
+ for (char c: text.toCharArray()) {
+ Character escChar = escapedChar(c);
+ if (escChar == 0) {
+ escaped.append(c);
+ } else {
+ escaped.append('|').append(escChar);
+ }
+ }
+
+ return escaped.toString();
+ }
+
+ @Override
+ public void printProgressMessage(JpsGantProjectBuilder project, String message) {
+ String escapedMessage = escape(message);
+ project.info("##teamcity[progressMessage '" + escapedMessage + "']");
+ }
+
+ @Override
+ public void printCompilationErrors(JpsGantProjectBuilder project, String compilerName, String messages) {
+ String escapedCompiler = escape(compilerName);
+ String escapedOutput = escape(messages);
+ project.info("##teamcity[compilationStarted compiler='" + escapedCompiler + "']");
+ project.info("##teamcity[message text='" + escapedOutput + "' status='ERROR']");
+ project.info("##teamcity[compilationFinished compiler='" + escapedCompiler + "']");
+ }
+
+ @Override
+ public void printCompilationStart(JpsGantProjectBuilder project, String compilerName) {
+ project.info("##teamcity[compilationStarted compiler='" + escape(compilerName) + "']");
+ }
+
+ @Override
+ public void printCompilationFinish(JpsGantProjectBuilder project, String compilerName) {
+ project.info("##teamcity[compilationFinished compiler='" + escape(compilerName) + "']");
+ }
+}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
new file mode 100644
index 000000000000..627c9f821b99
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.idea
+/**
+ * @author max
+ */
+public class IdeaProjectLoader {
+ public static String guessHome(Script script) {
+ File home = new File(script["gant.file"].substring("file:".length()))
+
+ while (home != null) {
+ if (home.isDirectory()) {
+ if (new File(home, ".idea").exists()) return home.getCanonicalPath()
+ }
+
+ home = home.getParentFile()
+ }
+
+ return null
+ }
+}