001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.geronimo.mavenplugins.car;
019:
020: import java.io.File;
021: import java.io.StringWriter;
022: import java.util.Collections;
023: import java.util.LinkedHashSet;
024: import java.util.List;
025: import java.util.Properties;
026:
027: import javax.xml.namespace.QName;
028:
029: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
030: import org.apache.geronimo.deployment.xbeans.ArtifactType;
031: import org.apache.geronimo.deployment.xbeans.EnvironmentType;
032: import org.apache.geronimo.kernel.repository.Artifact;
033: import org.apache.geronimo.kernel.repository.Environment;
034: import org.apache.geronimo.kernel.repository.ImportType;
035: import org.apache.velocity.Template;
036: import org.apache.velocity.VelocityContext;
037: import org.apache.velocity.app.Velocity;
038: import org.apache.velocity.app.VelocityEngine;
039: import org.apache.xmlbeans.XmlCursor;
040: import org.apache.xmlbeans.XmlObject;
041: import org.apache.xmlbeans.XmlOptions;
042:
043: //
044: // TODO: Rename to PreparePlanMojo
045: //
046:
047: /**
048: * Add module id and dependencies to a plan and process with velocity
049: *
050: * @version $Rev: 573884 $ $Date: 2007-09-08 10:37:55 -0700 (Sat, 08 Sep 2007) $
051: * @goal prepare-plan
052: */
053: public class PlanProcessorMojo extends AbstractCarMojo {
054: private static final String ENVIRONMENT_LOCAL_NAME = "environment";
055:
056: private static final QName ENVIRONMENT_QNAME = new QName(
057: "http://geronimo.apache.org/xml/ns/deployment-1.2",
058: "environment");
059:
060: /**
061: * Location of unproccesed plan, normally missing moduleId and dependencies.
062: *
063: * @parameter expression="${basedir}/src/main/plan"
064: * @required
065: */
066: protected File sourceDir = null;
067:
068: /**
069: * Directory to put the processed plan in.
070: *
071: * @parameter expression="${project.build.directory}/resources/META-INF"
072: * @required
073: */
074: protected File targetDir = null;
075:
076: /**
077: * Name of the unprocessed source and processed target plan file.
078: *
079: * @parameter default-value="plan.xml"
080: * @required
081: */
082: protected String planFileName = null;
083:
084: /**
085: * XXX
086: *
087: * @parameter expression="${project.build.directory}/resources/META-INF/plan.xml"
088: * @required
089: */
090: protected File targetFile = null;
091:
092: /**
093: * Dependencies explicitly listed in the car-maven-plugin configuration
094: *
095: * @parameter
096: */
097: private List<Dependency> dependencies = Collections.emptyList();
098:
099: /**
100: * Configuration of use of maven dependencies. If missing or if value element is false, use the explicit list in the car-maven-plugin configuration.
101: * If present and true, use the maven dependencies in the current pom file of scope null, runtime, or compile. In addition, the version of the maven
102: * dependency can be included or not depending on the includeVersion element.
103: *
104: * @parameter
105: */
106: private UseMavenDependencies useMavenDependencies;
107:
108: private VelocityContext createContext() {
109: VelocityContext context = new VelocityContext();
110:
111: // Load properties, It inherits them all!
112: Properties props = project.getProperties();
113: for (Object o : props.keySet()) {
114: String key = (String) o;
115: String value = props.getProperty(key);
116:
117: log.debug("Setting " + key + "=" + value);
118: context.put(key, value);
119: }
120:
121: context.put("pom", project);
122:
123: return context;
124: }
125:
126: protected void doExecute() throws Exception {
127: //
128: // FIXME: Do not need velocity here, we only need to filter,
129: // could use resources plugin to do this for us, or
130: // implement what resources plugin does here
131: //
132: // Also velocity does not handle property expansion of expressions like
133: // ${foo.bar} to the value of the "foo.bar" property :-(
134: //
135: // Might be better of just hand rolling something...
136: //
137:
138: VelocityContext context = createContext();
139:
140: VelocityEngine velocity = new VelocityEngine();
141: velocity.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH,
142: sourceDir.getAbsolutePath());
143:
144: // Don't spit out any logs
145: velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
146: "org.apache.velocity.runtime.log.NullLogSystem");
147: velocity.init();
148:
149: Template template = velocity.getTemplate(planFileName);
150: StringWriter writer = new StringWriter();
151: template.merge(context, writer);
152:
153: String plan = writer.toString();
154:
155: XmlObject doc = XmlObject.Factory.parse(plan);
156: XmlCursor xmlCursor = doc.newCursor();
157: LinkedHashSet<org.apache.geronimo.kernel.repository.Dependency> dependencies = toDependencies();
158: Artifact configId = new Artifact(project.getGroupId(), project
159: .getArtifactId(), project.getVersion(), "car");
160:
161: try {
162: mergeEnvironment(xmlCursor, configId, dependencies);
163:
164: if (targetDir.exists()) {
165: if (!targetDir.isDirectory()) {
166: throw new RuntimeException("TargetDir: "
167: + this .targetDir
168: + " exists and is not a directory");
169: }
170: } else {
171: targetDir.mkdirs();
172: }
173:
174: XmlOptions xmlOptions = new XmlOptions();
175: xmlOptions.setSavePrettyPrint();
176: doc.save(targetFile, xmlOptions);
177:
178: log.info("Generated: " + targetFile);
179: } finally {
180: xmlCursor.dispose();
181: }
182: }
183:
184: void mergeEnvironment(
185: final XmlCursor xmlCursor,
186: final Artifact configId,
187: final LinkedHashSet<org.apache.geronimo.kernel.repository.Dependency> dependencies) {
188: moveToFirstStartElement(xmlCursor);
189:
190: boolean atLeastOneChild = xmlCursor.toFirstChild();
191: if (!atLeastOneChild) {
192: // this is an empty element. Move to EndToken such XmlCursor.beginElement inserts an element inside it.
193: xmlCursor.toEndToken();
194: }
195: QName childName = xmlCursor.getName();
196: Environment oldEnvironment;
197:
198: if (childName != null
199: && childName.getLocalPart().equals(
200: ENVIRONMENT_LOCAL_NAME)) {
201: convertElement(xmlCursor, ENVIRONMENT_QNAME
202: .getNamespaceURI());
203: XmlObject xmlObject = xmlCursor.getObject();
204: EnvironmentType environmentType = (EnvironmentType) xmlObject
205: .copy().changeType(EnvironmentType.type);
206: oldEnvironment = EnvironmentBuilder
207: .buildEnvironment(environmentType);
208: xmlCursor.removeXml();
209: } else {
210: oldEnvironment = new Environment();
211: }
212:
213: Environment newEnvironment = new Environment();
214: newEnvironment.setConfigId(configId);
215: newEnvironment.setDependencies(dependencies);
216:
217: EnvironmentBuilder.mergeEnvironments(oldEnvironment,
218: newEnvironment);
219: EnvironmentType environmentType = EnvironmentBuilder
220: .buildEnvironmentType(oldEnvironment);
221:
222: xmlCursor.beginElement(ENVIRONMENT_QNAME);
223: XmlCursor element = environmentType.newCursor();
224:
225: try {
226: element.copyXmlContents(xmlCursor);
227: } finally {
228: element.dispose();
229: }
230: }
231:
232: private void moveToFirstStartElement(XmlCursor xmlCursor)
233: throws AssertionError {
234: xmlCursor.toStartDoc();
235: xmlCursor.toFirstChild();
236: while (!xmlCursor.currentTokenType().isStart()) {
237: if (!xmlCursor.toNextSibling()) {
238: break;
239: }
240: }
241: if (!xmlCursor.currentTokenType().isStart()) {
242: throw new AssertionError("Cannot find first start element");
243: }
244: }
245:
246: private void convertElement(final XmlCursor cursor,
247: final String namespace) {
248: cursor.push();
249: XmlCursor end = cursor.newCursor();
250:
251: try {
252: end.toCursor(cursor);
253: end.toEndToken();
254:
255: while (cursor.hasNextToken() && cursor.isLeftOf(end)) {
256: if (cursor.isStart()) {
257: if (!namespace.equals(cursor.getName()
258: .getNamespaceURI())) {
259: cursor.setName(new QName(namespace, cursor
260: .getName().getLocalPart()));
261: }
262: }
263:
264: cursor.toNextToken();
265: }
266:
267: cursor.pop();
268: } finally {
269: end.dispose();
270: }
271: }
272:
273: private LinkedHashSet<org.apache.geronimo.kernel.repository.Dependency> toDependencies() {
274: LinkedHashSet<org.apache.geronimo.kernel.repository.Dependency> dependencies = new LinkedHashSet<org.apache.geronimo.kernel.repository.Dependency>();
275:
276: if (useMavenDependencies == null
277: || !useMavenDependencies.isValue()) {
278: for (Dependency dependency : this .dependencies) {
279: org.apache.geronimo.kernel.repository.Dependency gdep = dependency
280: .toDependency();
281: dependencies.add(gdep);
282: }
283: } else {
284: List<org.apache.maven.model.Dependency> includedDependencies = project
285: .getOriginalModel().getDependencies();
286: List<org.apache.maven.model.Dependency> artifacts = project
287: .getDependencies();
288: for (org.apache.maven.model.Dependency dependency : includedDependencies) {
289: dependency = resolveDependency(dependency, artifacts);
290: if (includeDependency(dependency)) {
291: org.apache.geronimo.kernel.repository.Dependency gdep = toGeronimoDependency(
292: dependency, useMavenDependencies
293: .isIncludeVersion());
294: dependencies.add(gdep);
295: }
296: }
297: }
298:
299: return dependencies;
300: }
301:
302: private static org.apache.geronimo.kernel.repository.Dependency toGeronimoDependency(
303: final org.apache.maven.model.Dependency dependency,
304: boolean includeVersion) {
305: Artifact artifact = toGeronimoArtifact(dependency,
306: includeVersion);
307: return new org.apache.geronimo.kernel.repository.Dependency(
308: artifact, ImportType.ALL);
309: }
310:
311: private static Artifact toGeronimoArtifact(
312: final org.apache.maven.model.Dependency dependency,
313: boolean includeVersion) {
314: String groupId = dependency.getGroupId();
315: String artifactId = dependency.getArtifactId();
316: String version = includeVersion ? dependency.getVersion()
317: : null;
318: String type = dependency.getType();
319:
320: return new Artifact(groupId, artifactId, version, type);
321: }
322:
323: interface Inserter {
324: ArtifactType insert(EnvironmentType environmentType);
325: }
326: }
|