summaryrefslogtreecommitdiff
path: root/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
blob: 00f4c8bb0b6e2fc9ea5d9c878aeb3069b7f3d807 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jetbrains.plugins.gradle.tooling.builder

import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.FileVisitDetails
import org.gradle.api.file.FileVisitor
import org.gradle.api.java.archives.Manifest
import org.gradle.api.plugins.WarPlugin
import org.gradle.api.tasks.bundling.War
import org.gradle.util.GradleVersion
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.plugins.gradle.model.web.WebConfiguration
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
import org.jetbrains.plugins.gradle.tooling.internal.web.WarModelImpl
import org.jetbrains.plugins.gradle.tooling.internal.web.WebConfigurationImpl
import org.jetbrains.plugins.gradle.tooling.internal.web.WebResourceImpl

/**
 * @author Vladislav.Soroka
 * @since 6/25/2014
 */
class WarModelBuilderImpl implements ModelBuilderService {

  private static final String WEB_APP_DIR_PROPERTY = "webAppDir"
  private static final String WEB_APP_DIR_NAME_PROPERTY = "webAppDirName"

  @Override
  public boolean canBuild(String modelName) {
    return WebConfiguration.name.equals(modelName)
  }

  @Nullable
  @Override
  public Object buildAll(String modelName, Project project) {
    final WarPlugin warPlugin = project.plugins.findPlugin(WarPlugin)
    if (warPlugin == null) return null

    final String webAppDirName = !project.hasProperty(WEB_APP_DIR_NAME_PROPERTY) ?
                                 "src/main/webapp" : String.valueOf(project.property(WEB_APP_DIR_NAME_PROPERTY))

    final File webAppDir = !project.hasProperty(WEB_APP_DIR_PROPERTY) ? new File(project.projectDir, webAppDirName) :
                           (File)project.property(WEB_APP_DIR_PROPERTY)

    def warModels = []

    project.tasks.each { Task task ->
      if (task instanceof War) {
        final WarModelImpl warModel =
          new WarModelImpl((task as War).archiveName, webAppDirName, webAppDir)

        final List<WebConfiguration.WebResource> webResources = []
        final War warTask = task as War
        warModel.webXml = warTask.webXml
        warTask.rootSpec.setIncludeEmptyDirs(true)

        warTask.rootSpec.walk({ def resolver ->
          // def resolver ->
          //      in Gradle v1.x - org.gradle.api.internal.file.copy.CopySpecInternal
          //      in Gradle v2.x - org.gradle.api.internal.file.copy.CopySpecResolver

          if (resolver.metaClass.respondsTo(resolver, 'setIncludeEmptyDirs', boolean)) {
            resolver.setIncludeEmptyDirs(true)
          }
          if (!resolver.metaClass.respondsTo(resolver, 'getDestPath') ||
              !resolver.metaClass.respondsTo(resolver, 'getSource')) {
            throw new RuntimeException("${GradleVersion.current()} is not supported by web artifact importer")
          }

          final String relativePath = resolver.destPath.pathString
          final def sourcePaths

          if (resolver.metaClass.respondsTo(resolver, 'getSourcePaths')) {
            sourcePaths = resolver.getSourcePaths()
          } else if (resolver.this$0.metaClass.respondsTo(resolver, 'getSourcePaths')) {
            sourcePaths = resolver.this$0.getSourcePaths()
          } else {
            throw new RuntimeException("${GradleVersion.current()} is not supported by web artifact importer")
          }

          (sourcePaths.flatten() as List).each { def path ->
            if (path instanceof String) {
              def file = new File(warTask.project.projectDir, path)
              addPath(webResources, relativePath, "", file)
            }
          }


          resolver.source.visit(new FileVisitor() {
            @Override
            public void visitDir(FileVisitDetails dirDetails) {
              try {
                addPath(webResources, relativePath, dirDetails.path, dirDetails.file)
              }
              catch (Exception ignore) {
              }
            }

            @Override
            public void visitFile(FileVisitDetails fileDetails) {
              try {
                if (warTask.webXml == null ||
                    !fileDetails.file.canonicalPath.equals(warTask.webXml.canonicalPath)) {
                  addPath(webResources, relativePath, fileDetails.path, fileDetails.file)
                }
              }
              catch (Exception ignore) {
              }
            }
          })
        })

        warModel.webResources = webResources
        warModel.classpath = warTask.classpath.files

        Manifest manifest = warTask.manifest
        if (manifest != null) {
          def writer = new StringWriter()
          manifest.writeTo(writer)
          warModel.manifestContent = writer.toString()
        }
        warModels.add(warModel)
      }
    }

    new WebConfigurationImpl(warModels)
  }

  @NotNull
  @Override
  public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
    ErrorMessageBuilder.create(
      project, e, "Web project import errors"
    ).withDescription("Web Facets/Artifacts will not be configured")
  }

  private static addPath(List<WebConfiguration.WebResource> webResources, String warRelativePath, String fileRelativePath, File file) {
    warRelativePath = warRelativePath == null ? "" : warRelativePath

    WebConfiguration.WebResource webResource = new WebResourceImpl(warRelativePath, fileRelativePath, file)
    webResources.add(webResource)
  }
}