001 /**
002 *
003 * Copyright 2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.plugin.car;
019
020 import java.io.File;
021 import java.io.StringWriter;
022 import java.util.HashMap;
023 import java.util.Iterator;
024 import java.util.LinkedHashSet;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.Properties;
028
029 import javax.xml.namespace.QName;
030
031 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
032 import org.apache.geronimo.deployment.xbeans.ArtifactType;
033 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
034 import org.apache.geronimo.kernel.repository.Environment;
035 import org.apache.geronimo.kernel.repository.Artifact;
036 import org.apache.geronimo.kernel.repository.ImportType;
037
038 import org.apache.maven.model.Dependency;
039
040 import org.apache.velocity.Template;
041 import org.apache.velocity.VelocityContext;
042 import org.apache.velocity.app.VelocityEngine;
043
044 import org.apache.xmlbeans.XmlCursor;
045 import org.apache.xmlbeans.XmlObject;
046 import org.apache.xmlbeans.XmlOptions;
047
048 //
049 // TODO: Rename to PreparePlanMojo
050 //
051
052 /**
053 * Add dependencies to a plan and process with velocity
054 *
055 * @goal prepare-plan
056 *
057 * @version $Rev: 434144 $ $Date: 2006-08-23 21:56:43 +0200 (mer., 23 août 2006) $
058 */
059 public class PlanProcessorMojo
060 extends AbstractCarMojo
061 {
062 private static final String ENVIRONMENT_LOCAL_NAME = "environment";
063
064 private static final QName ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.1", ENVIRONMENT_LOCAL_NAME);
065
066 /**
067 * @parameter expression="${basedir}/src/plan"
068 * @required
069 */
070 private File sourceDir;
071
072 /**
073 * @parameter expression="${project.build.directory}/plan"
074 * @required
075 */
076 private File targetDir;
077
078 /**
079 * @parameter default-value="plan.xml"
080 * @required
081 */
082 private String planFileName;
083
084 /**
085 * @parameter expression="${project.build.directory}/plan/plan.xml"
086 * @required
087 */
088 private File targetFile;
089
090 /**
091 * @parameter expression="1.2"
092 * @required
093 */
094 private String geronimoVersion;
095
096 private VelocityContext createContext() {
097 VelocityContext context = new VelocityContext();
098
099 // 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 }