1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * 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, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.geronimo.deployment.service;
20
21 import java.beans.PropertyEditorManager;
22 import java.io.File;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.net.URI;
26 import java.net.URL;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.jar.JarFile;
30
31 import javax.xml.namespace.QName;
32
33 import org.apache.geronimo.common.DeploymentException;
34 import org.apache.geronimo.deployment.ConfigurationBuilder;
35 import org.apache.geronimo.deployment.DeploymentContext;
36 import org.apache.geronimo.deployment.ModuleIDBuilder;
37 import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
38 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
39 import org.apache.geronimo.deployment.util.DeploymentUtil;
40 import org.apache.geronimo.deployment.xbeans.ArtifactType;
41 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
42 import org.apache.geronimo.deployment.xbeans.ModuleDocument;
43 import org.apache.geronimo.deployment.xbeans.ModuleType;
44 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
45 import org.apache.geronimo.gbean.AbstractName;
46 import org.apache.geronimo.gbean.GBeanInfo;
47 import org.apache.geronimo.gbean.GBeanInfoBuilder;
48 import org.apache.geronimo.kernel.Kernel;
49 import org.apache.geronimo.kernel.Naming;
50 import org.apache.geronimo.kernel.config.ConfigurationAlreadyExistsException;
51 import org.apache.geronimo.kernel.config.ConfigurationManager;
52 import org.apache.geronimo.kernel.config.ConfigurationModuleType;
53 import org.apache.geronimo.kernel.config.ConfigurationStore;
54 import org.apache.geronimo.kernel.config.ConfigurationUtil;
55 import org.apache.geronimo.kernel.config.SimpleConfigurationManager;
56 import org.apache.geronimo.kernel.repository.Artifact;
57 import org.apache.geronimo.kernel.repository.ArtifactResolver;
58 import org.apache.geronimo.kernel.repository.Environment;
59 import org.apache.geronimo.kernel.repository.Repository;
60 import org.apache.xmlbeans.XmlCursor;
61 import org.apache.xmlbeans.XmlException;
62 import org.apache.xmlbeans.XmlObject;
63
64 /**
65 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
66 */
67 public class ServiceConfigBuilder implements ConfigurationBuilder {
68 private final Environment defaultEnvironment;
69 private final Collection repositories;
70
71 private static final QName MODULE_QNAME = ModuleDocument.type.getDocumentElementName();
72 public static final String SERVICE_MODULE = "ServiceModule";
73 private final Naming naming;
74 private final ConfigurationManager configurationManager;
75 private final NamespaceDrivenBuilderCollection serviceBuilders;
76
77 public ServiceConfigBuilder(Environment defaultEnvironment, Collection repositories, Naming naming) {
78 this(defaultEnvironment, repositories, Collections.EMPTY_LIST, naming, null);
79 }
80
81 public ServiceConfigBuilder(Environment defaultEnvironment, Collection repositories, Collection serviceBuilders, Kernel kernel) {
82 this(defaultEnvironment, repositories, serviceBuilders, kernel.getNaming(), ConfigurationUtil.getConfigurationManager(kernel));
83 }
84
85 public ServiceConfigBuilder(Environment defaultEnvironment, Collection repositories, Collection serviceBuilders, Naming naming) {
86 this(defaultEnvironment, repositories, serviceBuilders, naming, null);
87 }
88
89 private ServiceConfigBuilder(Environment defaultEnvironment, Collection repositories, Collection serviceBuilders, Naming naming, ConfigurationManager configurationManager) {
90 this.naming = naming;
91 this.configurationManager = configurationManager;
92
93 EnvironmentBuilder environmentBuilder = new EnvironmentBuilder();
94 this.defaultEnvironment = defaultEnvironment;
95
96 this.repositories = repositories;
97 this.serviceBuilders = new NamespaceDrivenBuilderCollection(serviceBuilders);
98 }
99
100 public Object getDeploymentPlan(File planFile, JarFile jarFile, ModuleIDBuilder idBuilder) throws DeploymentException {
101 if (planFile == null && jarFile == null) {
102 return null;
103 }
104
105 try {
106 XmlObject xmlObject;
107 if (planFile != null) {
108 xmlObject = XmlBeansUtil.parse(planFile.toURL(), getClass().getClassLoader());
109 } else {
110 URL path = DeploymentUtil.createJarURL(jarFile, "META-INF/geronimo-service.xml");
111 try {
112 xmlObject = XmlBeansUtil.parse(path, getClass().getClassLoader());
113 } catch (FileNotFoundException e) {
114
115
116 return null;
117 }
118 }
119 if(xmlObject == null) {
120 return null;
121 }
122
123 XmlCursor cursor = xmlObject.newCursor();
124 try {
125 cursor.toFirstChild();
126 if (!MODULE_QNAME.equals(cursor.getName())) {
127 return null;
128 }
129 } finally {
130 cursor.dispose();
131 }
132 ModuleDocument moduleDoc;
133 if (xmlObject instanceof ModuleDocument) {
134 moduleDoc = (ModuleDocument) xmlObject;
135 } else {
136 moduleDoc = (ModuleDocument) xmlObject.changeType(ModuleDocument.type);
137 }
138 XmlBeansUtil.validateDD(moduleDoc);
139
140 if(jarFile == null && (moduleDoc.getModule().getEnvironment() == null ||
141 moduleDoc.getModule().getEnvironment().getModuleId() == null ||
142 moduleDoc.getModule().getEnvironment().getModuleId().getArtifactId() == null)) {
143 if(moduleDoc.getModule().getEnvironment() == null) {
144 moduleDoc.getModule().addNewEnvironment();
145 }
146 if(moduleDoc.getModule().getEnvironment().getModuleId() == null) {
147 moduleDoc.getModule().getEnvironment().addNewModuleId();
148 }
149 String name = planFile.getName();
150 int pos = name.lastIndexOf('.');
151 if(pos > -1) {
152 name = name.substring(0, pos);
153 }
154 moduleDoc.getModule().getEnvironment().getModuleId().setArtifactId(name);
155 }
156 return moduleDoc.getModule();
157 } catch (XmlException e) {
158 throw new DeploymentException("Could not parse xml in plan", e);
159 } catch (IOException e) {
160 throw new DeploymentException("no plan at " + planFile, e);
161 }
162 }
163
164 public Artifact getConfigurationID(Object plan, JarFile module, ModuleIDBuilder idBuilder) throws IOException, DeploymentException {
165 ModuleType configType = (ModuleType) plan;
166 EnvironmentType environmentType = configType.getEnvironment();
167 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment);
168 idBuilder.resolve(environment, module == null ? "" : new File(module.getName()).getName(), "car");
169 if(!environment.getConfigId().isResolved()) {
170 throw new IllegalStateException("Service Module ID is not fully populated ("+environment.getConfigId()+")");
171 }
172 return environment.getConfigId();
173 }
174
175 public DeploymentContext buildConfiguration(boolean inPlaceDeployment, Artifact configId, Object plan, JarFile jar, Collection configurationStores, ArtifactResolver artifactResolver, ConfigurationStore targetConfigurationStore) throws IOException, DeploymentException {
176 ModuleType configType = (ModuleType) plan;
177
178 return buildConfiguration(inPlaceDeployment, configId, configType, jar, configurationStores, artifactResolver, targetConfigurationStore);
179 }
180
181 public DeploymentContext buildConfiguration(boolean inPlaceDeployment, Artifact configId, ModuleType moduleType, JarFile jar, Collection configurationStores, ArtifactResolver artifactResolver, ConfigurationStore targetConfigurationStore) throws DeploymentException, IOException {
182 ArtifactType type = moduleType.getEnvironment().isSetModuleId() ? moduleType.getEnvironment().getModuleId() : moduleType.getEnvironment().addNewModuleId();
183 type.setArtifactId(configId.getArtifactId());
184 type.setGroupId(configId.getGroupId());
185 type.setType(configId.getType());
186 type.setVersion(configId.getVersion().toString());
187 Environment environment = EnvironmentBuilder.buildEnvironment(moduleType.getEnvironment(), defaultEnvironment);
188 if(!environment.getConfigId().isResolved()) {
189 throw new IllegalStateException("Module ID should be fully resolved by now (not "+environment.getConfigId()+")");
190 }
191 File outfile;
192 try {
193 outfile = targetConfigurationStore.createNewConfigurationDir(configId);
194 } catch (ConfigurationAlreadyExistsException e) {
195 throw new DeploymentException(e);
196 }
197
198 DeploymentContext context = null;
199 try {
200 ConfigurationManager configurationManager = this.configurationManager;
201 if (configurationManager == null) {
202 configurationManager = new SimpleConfigurationManager(configurationStores, artifactResolver, repositories);
203 }
204
205 AbstractName moduleName = naming.createRootName(configId, configId.toString(), SERVICE_MODULE);
206 context = new DeploymentContext(outfile,
207 inPlaceDeployment && null != jar ? DeploymentUtil.toFile(jar) : null,
208 environment,
209 moduleName,
210 ConfigurationModuleType.SERVICE,
211 naming,
212 configurationManager,
213 repositories);
214 if(jar != null) {
215 File file = new File(jar.getName());
216 context.addIncludeAsPackedJar(URI.create(file.getName()), jar);
217 }
218
219 serviceBuilders.build(moduleType, context, context);
220 return context;
221 } catch (DeploymentException de) {
222 cleanupAfterFailedBuild(context, outfile);
223 throw de;
224 } catch (IOException ie) {
225 cleanupAfterFailedBuild(context, outfile);
226 throw ie;
227 } catch (RuntimeException re) {
228 cleanupAfterFailedBuild(context, outfile);
229 throw re;
230 } catch (Error e) {
231 cleanupAfterFailedBuild(context, outfile);
232 throw e;
233 }
234 }
235
236 private void cleanupAfterFailedBuild(DeploymentContext context, File directory) {
237 try {
238 if (context !=null) {
239 context.close();
240 }
241 } catch (DeploymentException de) {
242
243 } catch (IOException ioe) {
244
245 }
246 if (directory != null) {
247 DeploymentUtil.recursiveDelete(directory);
248 }
249 }
250
251 public static final GBeanInfo GBEAN_INFO;
252
253 static {
254 PropertyEditorManager.registerEditor(Environment.class, EnvironmentBuilder.class);
255
256 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ServiceConfigBuilder.class, CONFIG_BUILDER);
257
258 infoBuilder.addInterface(ConfigurationBuilder.class);
259
260 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true);
261 infoBuilder.addReference("Repository", Repository.class, "Repository");
262 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, "ModuleBuilder");
263 infoBuilder.addAttribute("kernel", Kernel.class, false, false);
264
265 infoBuilder.setConstructor(new String[]{"defaultEnvironment", "Repository", "ServiceBuilders", "kernel"});
266
267 GBEAN_INFO = infoBuilder.getBeanInfo();
268 }
269
270 public static GBeanInfo getGBeanInfo() {
271 return GBEAN_INFO;
272 }
273
274 }