View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.ear.util;
20  
21  import java.util.List;
22  import java.util.Set;
23  
24  import org.apache.maven.archiver.MavenArchiveConfiguration;
25  import org.apache.maven.archiver.MavenArchiver;
26  import org.apache.maven.artifact.DependencyResolutionRequiredException;
27  import org.apache.maven.execution.MavenSession;
28  import org.apache.maven.plugins.ear.EarModule;
29  import org.apache.maven.project.MavenProject;
30  import org.codehaus.plexus.archiver.jar.Manifest;
31  import org.codehaus.plexus.archiver.jar.ManifestException;
32  
33  /**
34   * A custom {@link MavenArchiver} implementation that takes care of setting the right classpath value according to the
35   * actual path of bundled files.
36   *
37   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
38   */
39  public class EarMavenArchiver extends MavenArchiver {
40      /**
41       * {@code Class-Path}.
42       */
43      public static final String CLASS_PATH_KEY = "Class-Path";
44  
45      private final List<EarModule> earModules;
46  
47      /**
48       * Creates an instance with the ear modules that will be packaged in the EAR archive.
49       *
50       * @param earModules the intitialized list of ear modules
51       */
52      public EarMavenArchiver(List<EarModule> earModules) {
53          this.earModules = earModules;
54      }
55  
56      /**
57       * @param project {@link MavenProject}
58       * @param config {@link MavenArchiveConfiguration}
59       * @throws ManifestException in case of an error
60       * @throws DependencyResolutionRequiredException in case of an resolution error.
61       * @return Manifest
62       * @deprecated
63       */
64      public Manifest getManifest(MavenProject project, MavenArchiveConfiguration config)
65              throws ManifestException, DependencyResolutionRequiredException {
66          return this.getManifest(null, project, config);
67      }
68  
69      /** {@inheritDoc} */
70      public Manifest getManifest(MavenSession session, MavenProject project, MavenArchiveConfiguration config)
71              throws ManifestException, DependencyResolutionRequiredException {
72          final Manifest manifest = super.getManifest(session, project, config);
73          if (config.getManifest().isAddClasspath()) {
74              String earManifestClassPathEntry =
75                      generateClassPathEntry(config.getManifest().getClasspathPrefix());
76              // Class-path can be customized. Let's make sure we don't overwrite this
77              // with our custom change!
78              final String userSuppliedClassPathEntry = getUserSuppliedClassPathEntry(config);
79              if (userSuppliedClassPathEntry != null) {
80                  earManifestClassPathEntry = userSuppliedClassPathEntry + " " + earManifestClassPathEntry;
81              }
82  
83              // Overwrite the existing one, if any
84              final Manifest.Attribute classPathAttr = manifest.getMainSection().getAttribute(CLASS_PATH_KEY);
85              if (classPathAttr != null) {
86                  classPathAttr.setValue(earManifestClassPathEntry);
87              } else {
88                  final Manifest.Attribute attr = new Manifest.Attribute(CLASS_PATH_KEY, earManifestClassPathEntry);
89                  manifest.addConfiguredAttribute(attr);
90              }
91          }
92          return manifest;
93      }
94  
95      /**
96       * Generates the {@code Class-Path} entry of the manifest according to the list of ear modules.
97       *
98       * @param classPathPrefix the classpath prefix to use
99       * @return the {@code Class-Path} entry
100      */
101     protected String generateClassPathEntry(String classPathPrefix) {
102         final StringBuilder classpath = new StringBuilder();
103         for (final EarModule earModule : earModules) {
104             if (!earModule.isExcluded()) {
105                 classpath.append(classPathPrefix).append(earModule.getUri()).append(" ");
106             }
107         }
108         return classpath.toString().trim();
109     }
110 
111     /**
112      * @param config {@link MavenArchiveConfiguration}
113      * @return The class path entry.
114      */
115     protected String getUserSuppliedClassPathEntry(MavenArchiveConfiguration config) {
116         if (config.getManifestEntries() != null) {
117             final Set<String> keys = config.getManifestEntries().keySet();
118             for (String key : keys) {
119                 String value = config.getManifestEntries().get(key);
120                 if ("Class-Path".equals(key) && value != null) {
121                     return value;
122                 }
123             }
124         }
125         return null;
126     }
127 }