View Javadoc

1   /**
2    *
3    * Copyright 2005 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.plugin.car;
19  
20  import java.io.File;
21  import java.io.StringWriter;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Properties;
28  
29  import javax.xml.namespace.QName;
30  
31  import org.apache.geronimo.deployment.service.EnvironmentBuilder;
32  import org.apache.geronimo.deployment.xbeans.ArtifactType;
33  import org.apache.geronimo.deployment.xbeans.EnvironmentType;
34  import org.apache.geronimo.kernel.repository.Environment;
35  import org.apache.geronimo.kernel.repository.Artifact;
36  import org.apache.geronimo.kernel.repository.ImportType;
37  
38  import org.apache.maven.model.Dependency;
39  
40  import org.apache.velocity.Template;
41  import org.apache.velocity.VelocityContext;
42  import org.apache.velocity.app.VelocityEngine;
43  
44  import org.apache.xmlbeans.XmlCursor;
45  import org.apache.xmlbeans.XmlObject;
46  import org.apache.xmlbeans.XmlOptions;
47  
48  //
49  // TODO: Rename to PreparePlanMojo
50  //
51  
52  /**
53   * Add dependencies to a plan and process with velocity
54   * 
55   * @goal prepare-plan
56   *
57   * @version $Rev: 434144 $ $Date: 2006-08-23 21:56:43 +0200 (mer., 23 août 2006) $
58   */
59  public class PlanProcessorMojo
60      extends AbstractCarMojo
61  {
62      private static final String ENVIRONMENT_LOCAL_NAME = "environment";
63  
64      private static final QName ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.1", ENVIRONMENT_LOCAL_NAME);
65  
66      /**
67       * @parameter expression="${basedir}/src/plan"
68       * @required
69       */
70      private File sourceDir;
71  
72      /**
73       * @parameter expression="${project.build.directory}/plan"
74       * @required
75       */
76      private File targetDir;
77  
78      /**
79       * @parameter default-value="plan.xml"
80       * @required
81       */
82      private String planFileName;
83  
84      /**
85       * @parameter expression="${project.build.directory}/plan/plan.xml"
86       * @required
87       */
88      private File targetFile;
89      
90      /**
91       * @parameter expression="1.2"
92       * @required     
93       */    
94      private String geronimoVersion;
95      
96      private VelocityContext createContext() {
97          VelocityContext context = new VelocityContext();
98  
99          // Load properties, It inherits them all!
100         Properties props = project.getProperties();
101         for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
102             String key = (String) iter.next();
103             String value = props.getProperty(key);
104 
105             log.debug("Setting " + key + "=" + value);
106             context.put(key, value);
107         }
108 
109         context.put("pom", project);
110 
111         return context;
112     }
113 
114     protected void doExecute() throws Exception {
115         //
116         // FIXME: Do not need velocity here, we only need to filter,
117         //        could use resources plugin to do this for us, or
118         //        implement what resources plugin does here
119         //
120         
121         VelocityContext context = createContext();
122 
123         VelocityEngine velocity = new VelocityEngine();
124         velocity.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, sourceDir.getAbsolutePath());
125         velocity.init();
126 
127         Template template = velocity.getTemplate(planFileName);
128         StringWriter writer = new StringWriter();
129         template.merge(context, writer);
130 
131         String plan = writer.toString();
132 
133         XmlObject doc = XmlObject.Factory.parse(plan);
134         XmlCursor xmlCursor = doc.newCursor();
135         LinkedHashSet dependencies = toDependencies();
136         Artifact configId = new Artifact(project.getGroupId(), project.getArtifactId(), project.getVersion(), "car");
137 
138         try {
139             mergeEnvironment(xmlCursor, configId, dependencies);
140             
141             if (targetDir.exists()) {
142                 if (!targetDir.isDirectory()) {
143                     throw new RuntimeException("TargetDir: " + this.targetDir + " exists and is not a directory");
144                 }
145             }
146             else {
147                 targetDir.mkdirs();
148             }
149 
150             XmlOptions xmlOptions = new XmlOptions();
151             xmlOptions.setSavePrettyPrint();
152             doc.save(targetFile, xmlOptions);
153             
154             log.info("Generated: " + targetFile);
155         }
156         finally {
157             xmlCursor.dispose();
158         }
159     }
160 
161     void mergeEnvironment(final XmlCursor xmlCursor, final Artifact configId, final LinkedHashSet dependencies) {
162         xmlCursor.toFirstContentToken();
163         xmlCursor.toFirstChild();
164         QName childName = xmlCursor.getName();
165         Environment oldEnvironment;
166         
167         if (childName != null && childName.getLocalPart().equals(ENVIRONMENT_LOCAL_NAME)) {
168             convertElement(xmlCursor, ENVIRONMENT_QNAME.getNamespaceURI());
169             XmlObject xmlObject = xmlCursor.getObject();
170             EnvironmentType environmentType = (EnvironmentType) xmlObject.copy().changeType(EnvironmentType.type);
171             oldEnvironment = EnvironmentBuilder.buildEnvironment(environmentType);
172             xmlCursor.removeXml();
173         }
174         else {
175             oldEnvironment = new Environment();
176         }
177 
178         Environment newEnvironment = new Environment();
179         newEnvironment.setConfigId(configId);
180         newEnvironment.setDependencies(dependencies);
181 
182         EnvironmentBuilder.mergeEnvironments(oldEnvironment, newEnvironment);
183         EnvironmentType environmentType = EnvironmentBuilder.buildEnvironmentType(oldEnvironment);
184 
185         xmlCursor.beginElement(ENVIRONMENT_QNAME);
186         XmlCursor element = environmentType.newCursor();
187 
188         try {
189             element.copyXmlContents(xmlCursor);
190         }
191         finally {
192             element.dispose();
193         }
194     }
195 
196     private void convertElement(final XmlCursor cursor, final String namespace) {
197         cursor.push();
198         XmlCursor end = cursor.newCursor();
199 
200         try {
201             end.toCursor(cursor);
202             end.toEndToken();
203 
204             while (cursor.hasNextToken() && cursor.isLeftOf(end)) {
205                 if (cursor.isStart()) {
206                     if (!namespace.equals(cursor.getName().getNamespaceURI())) {
207                         cursor.setName(new QName(namespace, cursor.getName().getLocalPart()));
208                     }
209                 }
210 
211                 cursor.toNextToken();
212             }
213 
214             cursor.pop();
215         }
216         finally {
217             end.dispose();
218         }
219     }
220 
221     private LinkedHashSet toDependencies() {
222         List artifacts = project.getDependencies();
223         LinkedHashSet dependencies = new LinkedHashSet();
224 
225         Iterator iter = artifacts.iterator();
226         while (iter.hasNext()) {
227             Dependency dependency = (Dependency) iter.next();
228 
229             //
230             // HACK: Does not appear that we can get the "extention" status of a dependency,
231             //       so specifically exclude the ones that we know about, like genesis
232             //
233 
234             if (dependency.getGroupId().startsWith("org.apache.geronimo.genesis")) {
235                 continue;
236             }
237 
238             org.apache.geronimo.kernel.repository.Dependency gdep = toGeronimoDependency(dependency);
239             if (gdep != null) {
240                 dependencies.add(gdep);
241             }
242         }
243 
244         return dependencies;
245     }
246 
247     private static org.apache.geronimo.kernel.repository.Dependency toGeronimoDependency(final Dependency dependency) {
248         Artifact artifact = toGeronimoArtifact(dependency);
249         String type = dependency.getType();
250         String scope = dependency.getScope();
251         String groupId = dependency.getGroupId();
252 
253         //!"org.apache.geronimo.specs".equals(groupId) jacc spec needed in plan.xml
254         if ("jar".equalsIgnoreCase(type) && !"junit".equals(groupId) && (scope == null || !scope.equals("provided"))) {
255             if (dependency.getVersion() != null) {
256                 artifact = new Artifact(
257                     artifact.getGroupId(),
258                     artifact.getArtifactId(),
259                     dependency.getVersion(),
260                     artifact.getType());
261             }
262             return new org.apache.geronimo.kernel.repository.Dependency(artifact, ImportType.CLASSES);
263         }
264         else if ("car".equalsIgnoreCase(type) && ("runtime").equalsIgnoreCase(scope)) {
265             return new org.apache.geronimo.kernel.repository.Dependency(artifact, ImportType.SERVICES);
266         }
267         else if ("car".equalsIgnoreCase(type) && ("compile".equalsIgnoreCase(scope))) {
268             return new org.apache.geronimo.kernel.repository.Dependency(artifact, ImportType.CLASSES);
269         }
270         else if ("car".equalsIgnoreCase(type) && (scope == null)) { //parent
271             return new org.apache.geronimo.kernel.repository.Dependency(artifact, ImportType.ALL);
272         }
273         else {
274             // not one of ours
275             return null;
276         }
277     }
278 
279     private static Artifact toGeronimoArtifact(final Dependency dependency) {
280         String groupId = dependency.getGroupId();
281         String artifactId = dependency.getArtifactId();
282         String version = null;
283         String type = dependency.getType();
284 
285         return new Artifact(groupId, artifactId, version, type);
286     }
287 
288     interface Inserter {
289         ArtifactType insert(EnvironmentType environmentType);
290     }
291 }