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 }