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 package org.apache.geronimo.client.builder;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.net.URI;
23 import java.net.URISyntaxException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.Map;
31 import java.util.StringTokenizer;
32 import java.util.HashMap;
33 import java.util.jar.Attributes;
34 import java.util.jar.JarFile;
35 import java.util.jar.Manifest;
36 import java.util.zip.ZipEntry;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.geronimo.client.AppClientContainer;
41 import org.apache.geronimo.client.StaticJndiContextPlugin;
42 import org.apache.geronimo.common.DeploymentException;
43 import org.apache.geronimo.deployment.DeploymentContext;
44 import org.apache.geronimo.deployment.ModuleIDBuilder;
45 import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
46 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
47 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
48 import org.apache.geronimo.deployment.util.DeploymentUtil;
49 import org.apache.geronimo.deployment.util.NestedJarFile;
50 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
51 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
52 import org.apache.geronimo.gbean.AbstractName;
53 import org.apache.geronimo.gbean.AbstractNameQuery;
54 import org.apache.geronimo.gbean.GBeanData;
55 import org.apache.geronimo.gbean.GBeanInfo;
56 import org.apache.geronimo.gbean.GBeanInfoBuilder;
57 import org.apache.geronimo.gbean.SingleElementCollection;
58 import org.apache.geronimo.j2ee.deployment.AppClientModule;
59 import org.apache.geronimo.j2ee.deployment.EARContext;
60 import org.apache.geronimo.j2ee.deployment.Module;
61 import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
62 import org.apache.geronimo.j2ee.deployment.SecurityBuilder;
63 import org.apache.geronimo.j2ee.deployment.CorbaGBeanNameSource;
64 import org.apache.geronimo.j2ee.deployment.NamingBuilder;
65 import org.apache.geronimo.j2ee.deployment.NamingBuilderCollection;
66 import org.apache.geronimo.j2ee.deployment.ConnectorModule;
67 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
68 import org.apache.geronimo.j2ee.management.impl.J2EEAppClientModuleImpl;
69 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
70 import org.apache.geronimo.kernel.Naming;
71 import org.apache.geronimo.kernel.config.ConfigurationAlreadyExistsException;
72 import org.apache.geronimo.kernel.config.ConfigurationModuleType;
73 import org.apache.geronimo.kernel.config.ConfigurationStore;
74 import org.apache.geronimo.kernel.config.Configuration;
75 import org.apache.geronimo.kernel.repository.Artifact;
76 import org.apache.geronimo.kernel.repository.Environment;
77 import org.apache.geronimo.kernel.repository.Repository;
78 import org.apache.geronimo.schema.SchemaConversionUtils;
79 import org.apache.geronimo.security.deploy.DefaultPrincipal;
80 import org.apache.geronimo.xbeans.geronimo.client.GerApplicationClientDocument;
81 import org.apache.geronimo.xbeans.geronimo.client.GerApplicationClientType;
82 import org.apache.geronimo.xbeans.geronimo.client.GerResourceType;
83 import org.apache.geronimo.xbeans.geronimo.naming.GerAbstractNamingEntryDocument;
84 import org.apache.geronimo.xbeans.j2ee.ApplicationClientDocument;
85 import org.apache.geronimo.xbeans.j2ee.ApplicationClientType;
86 import org.apache.xmlbeans.XmlException;
87 import org.apache.xmlbeans.XmlObject;
88 import org.apache.xmlbeans.XmlCursor;
89
90
91 /**
92 * @version $Rev:385232 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
93 */
94 public class AppClientModuleBuilder implements ModuleBuilder, CorbaGBeanNameSource {
95 private static final Log log = LogFactory.getLog(AppClientModuleBuilder.class);
96 private static final String LINE_SEP = System.getProperty("line.separator");
97
98 private final Environment defaultClientEnvironment;
99 private final Environment defaultServerEnvironment;
100 private final AbstractNameQuery corbaGBeanObjectName;
101
102 private final AbstractNameQuery transactionManagerObjectName;
103 private final AbstractNameQuery connectionTrackerObjectName;
104 private final SingleElementCollection connectorModuleBuilder;
105 private final SingleElementCollection securityBuilder;
106 private final NamespaceDrivenBuilderCollection serviceBuilder;
107 private final NamingBuilderCollection namingBuilders;
108
109 private final Collection repositories;
110
111 private static final String GERAPPCLIENT_NAMESPACE = GerApplicationClientDocument.type.getDocumentElementName().getNamespaceURI();
112
113 public AppClientModuleBuilder(Environment defaultClientEnvironment,
114 Environment defaultServerEnvironment,
115 AbstractNameQuery transactionManagerObjectName,
116 AbstractNameQuery connectionTrackerObjectName,
117 AbstractNameQuery corbaGBeanObjectName,
118 Collection repositories,
119 ModuleBuilder connectorModuleBuilder,
120 NamespaceDrivenBuilder securityBuilder,
121 NamespaceDrivenBuilder serviceBuilder,
122 Collection namingBuilders) {
123 this(defaultClientEnvironment,
124 defaultServerEnvironment,
125 transactionManagerObjectName,
126 connectionTrackerObjectName,
127 corbaGBeanObjectName,
128 repositories, new SingleElementCollection(connectorModuleBuilder),
129 new SingleElementCollection(securityBuilder),
130 serviceBuilder == null ? Collections.EMPTY_SET : Collections.singleton(serviceBuilder),
131 namingBuilders == null ? Collections.EMPTY_SET : namingBuilders);
132 }
133
134 public AppClientModuleBuilder(AbstractNameQuery transactionManagerObjectName,
135 AbstractNameQuery connectionTrackerObjectName,
136 AbstractNameQuery corbaGBeanObjectName,
137 Collection repositories,
138 Collection connectorModuleBuilder,
139 Collection securityBuilder,
140 Collection serviceBuilder,
141 Collection namingBuilders,
142 Environment defaultClientEnvironment,
143 Environment defaultServerEnvironment) {
144 this(defaultClientEnvironment,
145 defaultServerEnvironment,
146 transactionManagerObjectName,
147 connectionTrackerObjectName,
148 corbaGBeanObjectName,
149 repositories, new SingleElementCollection(connectorModuleBuilder),
150 new SingleElementCollection(securityBuilder),
151 serviceBuilder,
152 namingBuilders);
153 }
154
155 private AppClientModuleBuilder(Environment defaultClientEnvironment,
156 Environment defaultServerEnvironment,
157 AbstractNameQuery transactionManagerObjectName,
158 AbstractNameQuery connectionTrackerObjectName,
159 AbstractNameQuery corbaGBeanObjectName,
160 Collection repositories,
161 SingleElementCollection connectorModuleBuilder,
162 SingleElementCollection securityBuilder,
163 Collection serviceBuilder, Collection namingBuilders) {
164 this.defaultClientEnvironment = defaultClientEnvironment;
165 this.defaultServerEnvironment = defaultServerEnvironment;
166 this.corbaGBeanObjectName = corbaGBeanObjectName;
167 this.transactionManagerObjectName = transactionManagerObjectName;
168 this.connectionTrackerObjectName = connectionTrackerObjectName;
169 this.repositories = repositories;
170 this.connectorModuleBuilder = connectorModuleBuilder;
171 this.securityBuilder = securityBuilder;
172 this.serviceBuilder = new NamespaceDrivenBuilderCollection(serviceBuilder);
173 this.namingBuilders = new NamingBuilderCollection(namingBuilders, GerAbstractNamingEntryDocument.type.getDocumentElementName());
174 }
175
176
177 public AbstractNameQuery getCorbaGBeanName() {
178 return corbaGBeanObjectName;
179 }
180
181 private ModuleBuilder getConnectorModuleBuilder() {
182 return (ModuleBuilder) connectorModuleBuilder.getElement();
183 }
184
185 private org.apache.geronimo.j2ee.deployment.SecurityBuilder getSecurityBuilder() {
186 return (SecurityBuilder) securityBuilder.getElement();
187 }
188
189 public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
190 return createModule(plan, moduleFile, "app-client", null, null, null, naming, idBuilder);
191 }
192
193 public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
194 return createModule(plan, moduleFile, targetPath, specDDUrl, environment, earName, naming, idBuilder);
195 }
196
197 private Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment earEnvironment, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
198 assert moduleFile != null: "moduleFile is null";
199 assert targetPath != null: "targetPath is null";
200 assert !targetPath.endsWith("/"): "targetPath must not end with a '/'";
201 assert (earName == null) == (earEnvironment == null): "if earName is not null you must supply earEnvironment as well";
202
203 String specDD;
204 ApplicationClientType appClient;
205 try {
206 if (specDDUrl == null) {
207 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "META-INF/application-client.xml");
208 }
209
210
211
212 specDD = DeploymentUtil.readAll(specDDUrl);
213 } catch (Exception e) {
214
215 return null;
216 }
217
218 try {
219
220 XmlObject xmlObject = XmlBeansUtil.parse(specDD);
221 ApplicationClientDocument appClientDoc = convertToApplicationClientSchema(xmlObject);
222 appClient = appClientDoc.getApplicationClient();
223 } catch (XmlException e) {
224 throw new DeploymentException("Unable to parse application-client.xml", e);
225 }
226
227
228 boolean standAlone = earEnvironment == null;
229 GerApplicationClientType gerAppClient = getGeronimoAppClient(plan, moduleFile, standAlone, targetPath, appClient, earEnvironment);
230
231
232 EnvironmentType clientEnvironmentType = gerAppClient.getClientEnvironment();
233 Environment clientEnvironment = EnvironmentBuilder.buildEnvironment(clientEnvironmentType, defaultClientEnvironment);
234 if (standAlone) {
235 String name = new File(moduleFile.getName()).getName();
236 idBuilder.resolve(clientEnvironment, name + "_" + name, "jar");
237 } else {
238 Artifact earConfigId = earEnvironment.getConfigId();
239 idBuilder.resolve(clientEnvironment, earConfigId.getArtifactId() + "_" + targetPath, "jar");
240 }
241 EnvironmentType serverEnvironmentType = gerAppClient.getServerEnvironment();
242 Environment serverEnvironment = EnvironmentBuilder.buildEnvironment(serverEnvironmentType, defaultServerEnvironment);
243 if (!standAlone) {
244 EnvironmentBuilder.mergeEnvironments(earEnvironment, serverEnvironment);
245 serverEnvironment = earEnvironment;
246 if (!serverEnvironment.getConfigId().isResolved()) {
247 throw new IllegalStateException("Server environment module ID should be fully resolved (not " + serverEnvironment.getConfigId() + ")");
248 }
249 } else {
250 idBuilder.resolve(serverEnvironment, new File(moduleFile.getName()).getName(), "jar");
251 }
252
253 namingBuilders.buildEnvironment(appClient, gerAppClient, clientEnvironment);
254
255 if (earName == null) {
256 earName = naming.createRootName(earEnvironment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION);
257 }
258
259
260 AbstractName moduleName = naming.createChildName(earName, clientEnvironment.getConfigId().toString(), NameFactory.APP_CLIENT_MODULE);
261 AbstractName clientBaseName = naming.createRootName(clientEnvironment.getConfigId(), clientEnvironment.getConfigId().toString(), NameFactory.J2EE_APPLICATION);
262
263
264 Collection resourceModules = new ArrayList();
265 GerResourceType[] resources = gerAppClient.getResourceArray();
266 for (int i = 0; i < resources.length; i++) {
267 GerResourceType resource = resources[i];
268 String path;
269 JarFile connectorFile;
270 if (resource.isSetExternalRar()) {
271 path = resource.getExternalRar().trim();
272 Artifact artifact = Artifact.create(path);
273 File file = null;
274 for (Iterator iterator = repositories.iterator(); iterator.hasNext();) {
275 Repository repository = (Repository) iterator.next();
276 if (repository.contains(artifact)) {
277 file = repository.getLocation(artifact);
278 break;
279 }
280 }
281 if (file == null) {
282 throw new DeploymentException("Missing rar in repositories: " + path);
283 }
284 try {
285 connectorFile = new JarFile(file);
286 } catch (IOException e) {
287 throw new DeploymentException("Could not access rar contents", e);
288 }
289 } else {
290 path = resource.getInternalRar();
291 try {
292 connectorFile = new NestedJarFile(moduleFile, path);
293 } catch (IOException e) {
294 throw new DeploymentException("Could not locate connector inside ear", e);
295 }
296 }
297 XmlObject connectorPlan = resource.getConnector();
298 Module connectorModule = getConnectorModuleBuilder().createModule(connectorPlan, connectorFile, path, null, clientEnvironment, null, clientBaseName, naming, idBuilder);
299 resourceModules.add(connectorModule);
300 }
301
302 return new AppClientModule(standAlone, moduleName, clientBaseName, serverEnvironment, clientEnvironment, moduleFile, targetPath, appClient, gerAppClient, specDD, resourceModules);
303 }
304
305 GerApplicationClientType getGeronimoAppClient(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, ApplicationClientType appClient, Environment environment) throws DeploymentException {
306 GerApplicationClientType gerAppClient;
307 XmlObject rawPlan = null;
308 try {
309
310 try {
311 if (plan instanceof XmlObject) {
312 rawPlan = (XmlObject) plan;
313 } else {
314 if (plan != null) {
315 rawPlan = XmlBeansUtil.parse((File) plan);
316 } else {
317 URL path = DeploymentUtil.createJarURL(moduleFile, "META-INF/geronimo-application-client.xml");
318 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
319 }
320 }
321 } catch (IOException e) {
322
323 }
324
325
326 if (rawPlan != null) {
327 gerAppClient = (GerApplicationClientType) SchemaConversionUtils.fixGeronimoSchema(rawPlan, GerApplicationClientDocument.type.getDocumentElementName(), GerApplicationClientType.type);
328 } else {
329 String path;
330 if (standAlone) {
331
332 path = new File(moduleFile.getName()).getName();
333 } else {
334
335 path = targetPath;
336 }
337 gerAppClient = createDefaultPlan(path, appClient, standAlone, environment);
338 }
339 } catch (XmlException e) {
340 throw new DeploymentException(e);
341 }
342 return gerAppClient;
343 }
344
345 private GerApplicationClientType createDefaultPlan(String name, ApplicationClientType appClient, boolean standAlone, Environment environment) {
346 String id = appClient.getId();
347 if (id == null) {
348 id = name;
349 if (id.endsWith(".jar")) {
350 id = id.substring(0, id.length() - 4);
351 }
352 if (id.endsWith("/")) {
353 id = id.substring(0, id.length() - 1);
354 }
355 }
356
357 GerApplicationClientType geronimoAppClient = GerApplicationClientType.Factory.newInstance();
358 EnvironmentType clientEnvironmentType = geronimoAppClient.addNewClientEnvironment();
359 EnvironmentType serverEnvironmentType = geronimoAppClient.addNewServerEnvironment();
360
361
362
363
364
365
366
367
368
369
370 return geronimoAppClient;
371 }
372
373 static ApplicationClientDocument convertToApplicationClientSchema(XmlObject xmlObject) throws XmlException {
374 if (ApplicationClientDocument.type.equals(xmlObject.schemaType())) {
375 XmlBeansUtil.validateDD(xmlObject);
376 return (ApplicationClientDocument) xmlObject;
377 }
378 XmlCursor cursor = xmlObject.newCursor();
379 XmlCursor moveable = xmlObject.newCursor();
380 String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd";
381 String version = "1.4";
382 try {
383 SchemaConversionUtils.convertToSchema(cursor, SchemaConversionUtils.J2EE_NAMESPACE, schemaLocationURL, version);
384 cursor.toStartDoc();
385 cursor.toChild(SchemaConversionUtils.J2EE_NAMESPACE, "application-client");
386 cursor.toFirstChild();
387 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable);
388 } finally {
389 cursor.dispose();
390 moveable.dispose();
391 }
392 XmlObject result = xmlObject.changeType(ApplicationClientDocument.type);
393 if (result != null) {
394 XmlBeansUtil.validateDD(result);
395 return (ApplicationClientDocument) result;
396 }
397 XmlBeansUtil.validateDD(xmlObject);
398 return (ApplicationClientDocument) xmlObject;
399
400 }
401
402 public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repositories) throws DeploymentException {
403
404 JarFile moduleFile = module.getModuleFile();
405 try {
406 earContext.addIncludeAsPackedJar(URI.create(module.getTargetPath()), moduleFile);
407 } catch (IOException e) {
408 throw new DeploymentException("Unable to copy app client module jar into configuration: " + moduleFile.getName());
409 }
410 AppClientModule appClientModule = (AppClientModule) module;
411 appClientModule.setEarFile(earFile);
412
413 Environment clientEnvironment = appClientModule.getClientEnvironment();
414
415
416
417
418
419
420 File appClientDir;
421 try {
422 appClientDir = targetConfigurationStore.createNewConfigurationDir(clientEnvironment.getConfigId());
423 } catch (ConfigurationAlreadyExistsException e) {
424 throw new DeploymentException(e);
425 }
426
427
428 EARContext appClientDeploymentContext;
429 try {
430
431 appClientDeploymentContext = new EARContext(appClientDir,
432 null,
433 clientEnvironment,
434 ConfigurationModuleType.CAR,
435 earContext.getNaming(),
436 earContext.getConfigurationManager(),
437 null,
438 appClientModule.getAppClientName(),
439 transactionManagerObjectName,
440 connectionTrackerObjectName,
441 null,
442 null,
443 corbaGBeanObjectName
444 );
445 appClientModule.setEarContext(appClientDeploymentContext);
446 appClientModule.setRootEarContext(earContext);
447 } catch (DeploymentException e) {
448 cleanupAppClientDir(appClientDir);
449 throw e;
450 }
451 for (Iterator resources = appClientModule.getResourceModules().iterator(); resources.hasNext();) {
452 ConnectorModule connectorModule = (ConnectorModule) resources.next();
453 getConnectorModuleBuilder().installModule(connectorModule.getModuleFile(), appClientDeploymentContext, connectorModule, configurationStores, targetConfigurationStore, repositories);
454 }
455
456 }
457
458 public void initContext(EARContext earContext, Module clientModule, ClassLoader cl) throws DeploymentException {
459 AppClientModule appClientModule = ((AppClientModule) clientModule);
460 for (Iterator resources = appClientModule.getResourceModules().iterator(); resources.hasNext();) {
461 ConnectorModule connectorModule = (ConnectorModule) resources.next();
462 getConnectorModuleBuilder().initContext(appClientModule.getEarContext(), connectorModule, cl);
463 }
464 }
465
466 public void addGBeans(EARContext earContext, Module module, ClassLoader earClassLoader, Collection repositories) throws DeploymentException {
467
468 AppClientModule appClientModule = (AppClientModule) module;
469
470 ApplicationClientType appClient = (ApplicationClientType) appClientModule.getSpecDD();
471 GerApplicationClientType geronimoAppClient = (GerApplicationClientType) appClientModule.getVendorDD();
472
473
474 JarFile moduleFile = module.getModuleFile();
475 String mainClasss;
476 try {
477 Manifest manifest = moduleFile.getManifest();
478 if (manifest == null) {
479 throw new DeploymentException("App client module jar does not contain a manifest: " + moduleFile.getName());
480 }
481 mainClasss = manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
482 if (mainClasss == null) {
483 throw new DeploymentException("App client module jar does not have Main-Class defined in the manifest: " + moduleFile.getName());
484 }
485 String classPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
486 if (module.isStandAlone() && classPath != null) {
487 throw new DeploymentException("Manifest class path entry is not allowed in a standalone jar (J2EE 1.4 Section 8.2)");
488 }
489 } catch (IOException e) {
490 throw new DeploymentException("Could not get manifest from app client module: " + moduleFile.getName());
491 }
492
493
494 AbstractName appClientModuleName = appClientModule.getModuleName();
495
496
497 GBeanData appClientModuleGBeanData = new GBeanData(appClientModuleName, J2EEAppClientModuleImpl.GBEAN_INFO);
498 try {
499 appClientModuleGBeanData.setReferencePattern("J2EEServer", earContext.getServerName());
500 if (!module.isStandAlone()) {
501 appClientModuleGBeanData.setReferencePattern("J2EEApplication", earContext.getModuleName());
502 }
503 appClientModuleGBeanData.setAttribute("deploymentDescriptor", appClientModule.getOriginalSpecDD());
504
505 } catch (Exception e) {
506 throw new DeploymentException("Unable to initialize AppClientModule GBean", e);
507 }
508 try {
509 earContext.addGBean(appClientModuleGBeanData);
510 } catch (GBeanAlreadyExistsException e) {
511 throw new DeploymentException("Could not add application client module gbean to configuration", e);
512 }
513
514 EARContext appClientDeploymentContext = appClientModule.getEarContext();
515
516
517 ModuleIDBuilder idBuilder = new ModuleIDBuilder();
518 idBuilder.setDefaultGroup(appClientModule.getClientEnvironment().getConfigId().getGroupId());
519 idBuilder.setDefaultVersion(appClientModule.getClientEnvironment().getConfigId().getVersion());
520 try {
521 try {
522
523
524 namingBuilders.initContext(appClient, geronimoAppClient, appClientDeploymentContext.getConfiguration(), earContext.getConfiguration(), appClientModule);
525
526 URI moduleBase = new URI(appClientModule.getTargetPath());
527 try {
528 appClientDeploymentContext.addIncludeAsPackedJar(moduleBase, moduleFile);
529 } catch (IOException e) {
530 throw new DeploymentException("Unable to copy app client module jar into configuration: " + moduleFile.getName());
531 }
532
533
534 addManifestClassPath(appClientDeploymentContext, appClientModule.getEarFile(), moduleFile, moduleBase);
535
536
537 ClassLoader appClientClassLoader = appClientDeploymentContext.getClassLoader();
538
539
540 if (geronimoAppClient != null) {
541 serviceBuilder.build(geronimoAppClient, appClientDeploymentContext, appClientDeploymentContext);
542
543
544 for (Iterator resources = appClientModule.getResourceModules().iterator(); resources.hasNext();) {
545 ConnectorModule connectorModule = (ConnectorModule) resources.next();
546 getConnectorModuleBuilder().addGBeans(appClientDeploymentContext, connectorModule, appClientClassLoader, repositories);
547 }
548 }
549
550
551
552 AbstractName jndiContextName = earContext.getNaming().createChildName(appClientDeploymentContext.getModuleName(), "StaticJndiContext", "StaticJndiContext");
553 GBeanData jndiContextGBeanData = new GBeanData(jndiContextName, StaticJndiContextPlugin.GBEAN_INFO);
554 try {
555 Map buildingContext = new HashMap();
556 buildingContext.put(NamingBuilder.JNDI_KEY, new HashMap());
557 buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, jndiContextName);
558 Configuration localConfiguration = appClientDeploymentContext.getConfiguration();
559 Configuration remoteConfiguration = earContext.getConfiguration();
560 namingBuilders.buildNaming(appClient, geronimoAppClient, localConfiguration, remoteConfiguration, appClientModule, buildingContext);
561 jndiContextGBeanData.setAttribute("context", buildingContext.get(NamingBuilder.JNDI_KEY));
562 } catch (DeploymentException e) {
563 throw e;
564 } catch (Exception e) {
565 throw new DeploymentException("Unable to construct jndi context for AppClientModule GBean", e);
566 }
567 appClientDeploymentContext.addGBean(jndiContextGBeanData);
568
569
570 AbstractName appClientContainerName = appClientDeploymentContext.getModuleName();
571 GBeanData appClientContainerGBeanData = new GBeanData(appClientContainerName, AppClientContainer.GBEAN_INFO);
572 try {
573 appClientContainerGBeanData.setAttribute("mainClassName", mainClasss);
574 appClientContainerGBeanData.setAttribute("appClientModuleName", appClientModuleName);
575 String callbackHandlerClassName = null;
576 if (appClient.isSetCallbackHandler()) {
577 callbackHandlerClassName = appClient.getCallbackHandler().getStringValue().trim();
578 }
579 if (geronimoAppClient.isSetCallbackHandler()) {
580 callbackHandlerClassName = geronimoAppClient.getCallbackHandler().trim();
581 }
582 String realmName = null;
583 if (geronimoAppClient.isSetRealmName()) {
584 realmName = geronimoAppClient.getRealmName().trim();
585 }
586 if (callbackHandlerClassName != null && realmName == null) {
587 throw new DeploymentException("You must specify a realm name with the callback handler");
588 }
589 if (realmName != null) {
590 appClientContainerGBeanData.setAttribute("realmName", realmName);
591 appClientContainerGBeanData.setAttribute("callbackHandlerClassName", callbackHandlerClassName);
592 } else if (geronimoAppClient.isSetDefaultPrincipal()) {
593 DefaultPrincipal defaultPrincipal = getSecurityBuilder().buildDefaultPrincipal(geronimoAppClient.getDefaultPrincipal());
594 appClientContainerGBeanData.setAttribute("defaultPrincipal", defaultPrincipal);
595 }
596 appClientContainerGBeanData.setReferencePattern("JNDIContext", jndiContextName);
597 } catch (Exception e) {
598 throw new DeploymentException("Unable to initialize AppClientModule GBean", e);
599 }
600 appClientDeploymentContext.addGBean(appClientContainerGBeanData);
601
602
603 earContext.addAdditionalDeployment(appClientDeploymentContext.getConfigurationData());
604 } finally {
605 if (appClientDeploymentContext != null) {
606 try {
607 appClientDeploymentContext.close();
608 } catch (IOException e) {
609
610 }
611 }
612 }
613
614 } catch (Throwable e) {
615 File appClientDir = appClientDeploymentContext.getBaseDir();
616 cleanupAppClientDir(appClientDir);
617 if (e instanceof Error) {
618 throw (Error) e;
619 } else if (e instanceof DeploymentException) {
620 throw (DeploymentException) e;
621 } else if (e instanceof Exception) {
622 throw new DeploymentException(e);
623 }
624 throw new Error(e);
625 }
626 }
627
628 public String getSchemaNamespace() {
629 return GERAPPCLIENT_NAMESPACE;
630 }
631
632 public void addManifestClassPath(DeploymentContext deploymentContext, JarFile earFile, JarFile jarFile, URI jarFileLocation) throws DeploymentException {
633 Manifest manifest;
634 try {
635 manifest = jarFile.getManifest();
636 } catch (IOException e) {
637 throw new DeploymentException("Could not read manifest: " + jarFileLocation);
638 }
639
640 if (manifest == null) {
641 return;
642 }
643 String manifestClassPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
644 if (manifestClassPath == null) {
645 return;
646 }
647
648 for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
649 String path = tokenizer.nextToken();
650
651 URI pathUri;
652 try {
653 pathUri = new URI(path);
654 } catch (URISyntaxException e) {
655 throw new DeploymentException("Invalid manifest classpath entry: jarFile=" + jarFileLocation + ", path=" + path);
656 }
657
658 if (!pathUri.getPath().endsWith(".jar")) {
659 throw new DeploymentException("Manifest class path entries must end with the .jar extension (J2EE 1.4 Section 8.2): jarFile=" + jarFileLocation + ", path=" + path);
660 }
661 if (pathUri.isAbsolute()) {
662 throw new DeploymentException("Manifest class path entries must be relative (J2EE 1.4 Section 8.2): jarFile=" + jarFileLocation + ", path=" + path);
663 }
664
665
666 URI classPathJarLocation = jarFileLocation.resolve(pathUri);
667 File classPathFile = deploymentContext.getTargetFile(classPathJarLocation);
668
669
670
671 if (!classPathFile.exists()) {
672
673 ZipEntry entry = earFile.getEntry(classPathJarLocation.getPath());
674 if (entry == null) {
675 throw new DeploymentException("Cound not find manifest class path entry: jarFile=" + jarFileLocation + ", path=" + path);
676 }
677
678 try {
679
680 deploymentContext.addFile(classPathJarLocation, earFile, entry);
681 } catch (IOException e) {
682 throw new DeploymentException("Cound not copy manifest class path entry into configuration: jarFile=" + jarFileLocation + ", path=" + path, e);
683 }
684
685 JarFile classPathJarFile;
686 try {
687 classPathJarFile = new JarFile(classPathFile);
688 } catch (IOException e) {
689 throw new DeploymentException("Manifest class path entries must be a valid jar file (J2EE 1.4 Section 8.2): jarFile=" + jarFileLocation + ", path=" + path, e);
690 }
691
692
693 addManifestClassPath(deploymentContext, earFile, classPathJarFile, classPathJarLocation);
694 }
695 }
696 }
697
698 private boolean cleanupAppClientDir(File configurationDir) {
699 LinkedList cannotBeDeletedList = new LinkedList();
700
701 if (!DeploymentUtil.recursiveDelete(configurationDir, cannotBeDeletedList)) {
702
703 log.warn("Unable to delete " + cannotBeDeletedList.size() +
704 " files while recursively deleting directory "
705 + configurationDir + LINE_SEP +
706 "The first file that could not be deleted was:" + LINE_SEP + " " +
707 (!cannotBeDeletedList.isEmpty() ? cannotBeDeletedList.getFirst() : ""));
708 return false;
709 }
710 return true;
711 }
712
713 public static final GBeanInfo GBEAN_INFO;
714
715 static {
716 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(AppClientModuleBuilder.class, NameFactory.MODULE_BUILDER);
717 infoBuilder.addAttribute("defaultClientEnvironment", Environment.class, true, true);
718 infoBuilder.addAttribute("defaultServerEnvironment", Environment.class, true, true);
719 infoBuilder.addAttribute("transactionManagerObjectName", AbstractNameQuery.class, true);
720 infoBuilder.addAttribute("connectionTrackerObjectName", AbstractNameQuery.class, true);
721 infoBuilder.addAttribute("corbaGBeanObjectName", AbstractNameQuery.class, true);
722 infoBuilder.addReference("Repositories", Repository.class, "Repository");
723 infoBuilder.addReference("ConnectorModuleBuilder", ModuleBuilder.class, NameFactory.MODULE_BUILDER);
724 infoBuilder.addReference("SecurityBuilder", SecurityBuilder.class, NameFactory.MODULE_BUILDER);
725 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
726 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER);
727
728 infoBuilder.addInterface(ModuleBuilder.class);
729
730 infoBuilder.setConstructor(new String[]{"transactionManagerObjectName",
731 "connectionTrackerObjectName",
732 "corbaGBeanObjectName",
733 "Repositories",
734 "ConnectorModuleBuilder",
735 "SecurityBuilder",
736 "ServiceBuilders",
737 "NamingBuilders",
738 "defaultClientEnvironment",
739 "defaultServerEnvironment",
740 });
741
742 GBEAN_INFO = infoBuilder.getBeanInfo();
743 }
744
745 public static GBeanInfo getGBeanInfo() {
746 return GBEAN_INFO;
747 }
748
749 }