001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. 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.deployment;
019
020 import java.io.ByteArrayInputStream;
021 import java.io.File;
022 import java.io.FileOutputStream;
023 import java.io.IOException;
024 import java.io.InputStream;
025 import java.io.OutputStream;
026 import java.net.URI;
027 import java.net.URISyntaxException;
028 import java.net.URL;
029 import java.util.ArrayList;
030 import java.util.Collection;
031 import java.util.Collections;
032 import java.util.HashSet;
033 import java.util.LinkedHashMap;
034 import java.util.LinkedHashSet;
035 import java.util.List;
036 import java.util.Map;
037 import java.util.Set;
038 import java.util.StringTokenizer;
039 import java.util.jar.Attributes;
040 import java.util.jar.JarFile;
041 import java.util.jar.Manifest;
042 import java.util.zip.ZipEntry;
043 import java.util.zip.ZipFile;
044
045 import org.apache.geronimo.common.DeploymentException;
046 import org.apache.geronimo.deployment.util.DeploymentUtil;
047 import org.apache.geronimo.gbean.AbstractName;
048 import org.apache.geronimo.gbean.AbstractNameQuery;
049 import org.apache.geronimo.gbean.GBeanData;
050 import org.apache.geronimo.gbean.GBeanInfo;
051 import org.apache.geronimo.gbean.GReferenceInfo;
052 import org.apache.geronimo.gbean.ReferencePatterns;
053 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
054 import org.apache.geronimo.kernel.GBeanNotFoundException;
055 import org.apache.geronimo.kernel.Naming;
056 import org.apache.geronimo.kernel.config.Configuration;
057 import org.apache.geronimo.kernel.config.ConfigurationData;
058 import org.apache.geronimo.kernel.config.ConfigurationManager;
059 import org.apache.geronimo.kernel.config.ConfigurationModuleType;
060 import org.apache.geronimo.kernel.config.NoSuchConfigException;
061 import org.apache.geronimo.kernel.repository.Artifact;
062 import org.apache.geronimo.kernel.repository.Environment;
063
064 /**
065 * @version $Rev:385232 $ $Date: 2007-07-23 21:41:35 -0400 (Mon, 23 Jul 2007) $
066 */
067 public class DeploymentContext {
068 private final File baseDir;
069 private final File inPlaceConfigurationDir;
070 private final ResourceContext resourceContext;
071 private final byte[] buffer = new byte[4096];
072 private final Map<String, ConfigurationData> childConfigurationDatas = new LinkedHashMap<String, ConfigurationData>();
073 private final ConfigurationManager configurationManager;
074 private final Configuration configuration;
075 private final Naming naming;
076 private final List<ConfigurationData> additionalDeployment = new ArrayList<ConfigurationData>();
077 protected final AbstractName moduleName;
078
079 public DeploymentContext(File baseDir, File inPlaceConfigurationDir, Environment environment, AbstractName moduleName, ConfigurationModuleType moduleType, Naming naming, ConfigurationManager configurationManager, Collection repositories) throws DeploymentException {
080 this(baseDir, inPlaceConfigurationDir, environment, moduleName, moduleType, naming, createConfigurationManager(configurationManager, repositories));
081 }
082
083 public DeploymentContext(File baseDir, File inPlaceConfigurationDir, Environment environment, AbstractName moduleName, ConfigurationModuleType moduleType, Naming naming, ConfigurationManager configurationManager) throws DeploymentException {
084 if (baseDir == null) throw new NullPointerException("baseDir is null");
085 if (environment == null) throw new NullPointerException("environment is null");
086 if (moduleType == null) throw new NullPointerException("type is null");
087 if (configurationManager == null) throw new NullPointerException("configurationManager is null");
088
089 if (!baseDir.exists()) {
090 baseDir.mkdirs();
091 }
092 this.baseDir = baseDir;
093
094 this.inPlaceConfigurationDir = inPlaceConfigurationDir;
095
096 this.moduleName = moduleName;
097
098 this.naming = naming;
099
100 this.configuration = createTempConfiguration(environment, moduleType, baseDir, inPlaceConfigurationDir, configurationManager, naming);
101
102 this.configurationManager = configurationManager;
103
104 if (null == inPlaceConfigurationDir) {
105 resourceContext = new CopyResourceContext(configuration, baseDir);
106 } else {
107 resourceContext = new InPlaceResourceContext(configuration, inPlaceConfigurationDir);
108 }
109 }
110
111 private static ConfigurationManager createConfigurationManager(ConfigurationManager configurationManager, Collection repositories) {
112 return new DeploymentConfigurationManager(configurationManager, repositories);
113 }
114
115 private static Configuration createTempConfiguration(Environment environment, ConfigurationModuleType moduleType, File baseDir, File inPlaceConfigurationDir, ConfigurationManager configurationManager, Naming naming) throws DeploymentException {
116 try {
117 configurationManager.loadConfiguration(new ConfigurationData(moduleType, null, null, null, environment, baseDir, inPlaceConfigurationDir, naming));
118 return configurationManager.getConfiguration(environment.getConfigId());
119 } catch (Exception e) {
120 throw new DeploymentException("Unable to create configuration for deployment", e);
121 }
122 }
123
124 public ConfigurationManager getConfigurationManager() {
125 return configurationManager;
126 }
127
128 public Artifact getConfigID() {
129 return configuration.getId();
130 }
131
132 public File getBaseDir() {
133 return baseDir;
134 }
135
136 public File getInPlaceConfigurationDir() {
137 return inPlaceConfigurationDir;
138 }
139
140 public Naming getNaming() {
141 return naming;
142 }
143
144 public GBeanData addGBean(String name, GBeanInfo gbeanInfo) throws GBeanAlreadyExistsException {
145 if (name == null) throw new NullPointerException("name is null");
146 if (gbeanInfo == null) throw new NullPointerException("gbean is null");
147 GBeanData gbean = new GBeanData(gbeanInfo);
148 configuration.addGBean(name, gbean);
149 return gbean;
150 }
151
152 public void addGBean(GBeanData gbean) throws GBeanAlreadyExistsException {
153 if (gbean == null) throw new NullPointerException("gbean is null");
154 if (gbean.getAbstractName() == null) throw new NullPointerException("gbean.getAbstractName() is null");
155 configuration.addGBean(gbean);
156 }
157
158 public void removeGBean(AbstractName name) throws GBeanNotFoundException {
159 if (name == null) throw new NullPointerException("name is null");
160 configuration.removeGBean(name);
161 }
162
163 public Set<AbstractName> getGBeanNames() {
164 return new HashSet<AbstractName>(configuration.getGBeans().keySet());
165 }
166
167 /**
168 * @deprecated use findGBeans(pattern)
169 * @param pattern Search for gbeans whose name matches pattern.
170 * @return the set of gbeans whose name matches the pattern.
171 */
172 public Set<AbstractName> listGBeans(AbstractNameQuery pattern) {
173 return findGBeans(pattern);
174 }
175
176 public AbstractName findGBean(AbstractNameQuery pattern) throws GBeanNotFoundException {
177 return configuration.findGBean(pattern);
178 }
179
180 public AbstractName findGBean(Set<AbstractNameQuery> patterns) throws GBeanNotFoundException {
181 return configuration.findGBean(patterns);
182 }
183
184 public LinkedHashSet<AbstractName> findGBeans(AbstractNameQuery pattern) {
185 return configuration.findGBeans(pattern);
186 }
187
188 public LinkedHashSet<GBeanData> findGBeanDatas(Configuration configuration, AbstractNameQuery pattern) {
189 return configuration.findGBeanDatas(configuration, Collections.singleton(pattern));
190 }
191
192 public LinkedHashSet<AbstractName> findGBeans(Set<AbstractNameQuery> patterns) {
193 return configuration.findGBeans(patterns);
194 }
195
196 public GBeanData getGBeanInstance(AbstractName name) throws GBeanNotFoundException {
197 Map gbeans = configuration.getGBeans();
198 GBeanData gbeanData = (GBeanData) gbeans.get(name);
199 if (gbeanData == null) {
200 throw new GBeanNotFoundException(name);
201 }
202 return gbeanData;
203 }
204
205 /**
206 * Add a packed jar file into the deployment context and place it into the
207 * path specified in the target path. The newly added packed jar is added
208 * to the classpath of the configuration.
209 *
210 * @param targetPath where the packed jar file should be placed
211 * @param jarFile the jar file to copy
212 * @throws IOException if there's a problem copying the jar file
213 */
214 public void addIncludeAsPackedJar(URI targetPath, JarFile jarFile) throws IOException {
215 resourceContext.addIncludeAsPackedJar(targetPath, jarFile);
216 }
217
218 /**
219 * Add a ZIP file entry into the deployment context and place it into the
220 * path specified in the target path. The newly added entry is added
221 * to the classpath of the configuration.
222 *
223 * @param targetPath where the ZIP file entry should be placed
224 * @param zipFile the ZIP file
225 * @param zipEntry the ZIP file entry
226 * @throws IOException if there's a problem copying the ZIP entry
227 */
228 public void addInclude(URI targetPath, ZipFile zipFile, ZipEntry zipEntry) throws IOException {
229 resourceContext.addInclude(targetPath, zipFile, zipEntry);
230 }
231
232 /**
233 * Add a file into the deployment context and place it into the
234 * path specified in the target path. The newly added file is added
235 * to the classpath of the configuration.
236 *
237 * @param targetPath where the file should be placed
238 * @param source the URL of file to be copied
239 * @throws IOException if there's a problem copying the ZIP entry
240 */
241 public void addInclude(URI targetPath, URL source) throws IOException {
242 resourceContext.addInclude(targetPath, source);
243 }
244
245 /**
246 * Add a file into the deployment context and place it into the
247 * path specified in the target path. The newly added file is added
248 * to the classpath of the configuration.
249 *
250 * @param targetPath where the file should be placed
251 * @param source the file to be copied
252 * @throws IOException if there's a problem copying the ZIP entry
253 */
254 public void addInclude(URI targetPath, File source) throws IOException {
255 resourceContext.addInclude(targetPath, source);
256 }
257
258 interface JarFileFactory {
259 JarFile newJarFile(URI relativeURI) throws IOException;
260
261 String getManifestClassPath(JarFile jarFile) throws IOException;
262 }
263
264 private class DefaultJarFileFactory implements JarFileFactory {
265
266 public JarFile newJarFile(URI relativeURI) throws IOException {
267 File targetFile = getTargetFile(relativeURI);
268 try {
269 return new JarFile(targetFile);
270 } catch (IOException e) {
271 throw (IOException)new IOException("Could not create JarFile for file: " + targetFile).initCause(e);
272 }
273 }
274
275 public String getManifestClassPath(JarFile jarFile) throws IOException {
276 Manifest manifest = jarFile.getManifest();
277 if (manifest == null) {
278 return null;
279 }
280 return manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
281 }
282 }
283
284 public void getCompleteManifestClassPath(JarFile moduleFile, URI moduleBaseUri, URI resolutionUri, ClassPathList classpath, ModuleList exclusions) throws DeploymentException {
285 List<DeploymentException> problems = new ArrayList<DeploymentException>();
286 getCompleteManifestClassPath(moduleFile, moduleBaseUri, resolutionUri, classpath, exclusions, new DefaultJarFileFactory(), problems);
287 if (!problems.isEmpty()) {
288 if (problems.size() == 1) {
289 throw problems.get(0);
290 }
291 throw new DeploymentException("Determining complete manifest classpath unsuccessful:", problems);
292 }
293 }
294
295 /**
296 * Recursively construct the complete set of paths in the ear for the manifest classpath of the supplied modulefile.
297 * Used only in PersistenceUnitBuilder to figure out if a persistence.xml relates to the starting module. Having a classloader for
298 * each ejb module would eliminate the need for this and be more elegant.
299 *
300 * @param moduleFile the module that we start looking at classpaths at, in the car.
301 * @param moduleBaseUri where the moduleFile is inside the car file. For an (unpacked) war this ends with / which means we also need:
302 * @param resolutionUri the uri to resolve all entries against. For a module such as an ejb jar that is part of the
303 * root ear car it is ".". For a sub-configuration such as a war it is the "reverse" of the path to the war file in the car.
304 * For instance, if the war file is foo/bar/myweb.war, the resolutionUri is "../../..".
305 * @param classpath the classpath list we are constructing.
306 * @param exclusions the paths to not investigate. These are typically the other modules in the ear/car file: they will have their contents processed for themselves.
307 * @param factory the factory for constructing JarFiles and the way to extract the manifest classpath from a JarFile. Introduced to make
308 * testing plausible, but may be useful for in-IDE deployment.
309 * @param problems List to save all the problems we encounter.
310 * @throws org.apache.geronimo.common.DeploymentException
311 * if something goes wrong.
312 */
313 public void getCompleteManifestClassPath(JarFile moduleFile, URI moduleBaseUri, URI resolutionUri, ClassPathList classpath, ModuleList exclusions, JarFileFactory factory, List<DeploymentException> problems) throws DeploymentException {
314 String manifestClassPath;
315 try {
316 manifestClassPath = factory.getManifestClassPath(moduleFile);
317 } catch (IOException e) {
318 problems.add(new DeploymentException(printInfo("Could not read manifest: " + moduleBaseUri, moduleBaseUri, classpath, exclusions), e));
319 return;
320 }
321
322 if (manifestClassPath == null) {
323 return;
324 }
325
326 for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
327 String path = tokenizer.nextToken();
328
329 URI pathUri;
330 try {
331 pathUri = new URI(path);
332 } catch (URISyntaxException e) {
333 problems.add(new DeploymentException(printInfo("Invalid manifest classpath entry, path=" + path, moduleBaseUri, classpath, exclusions)));
334 return;
335 }
336
337 if (!pathUri.getPath().endsWith(".jar")) {
338 problems.add(new DeploymentException(printInfo("Manifest class path entries must end with the .jar extension (J2EE 1.4 Section 8.2): path=" + path, moduleBaseUri, classpath, exclusions)));
339 return;
340 }
341 if (pathUri.isAbsolute()) {
342 problems.add(new DeploymentException(printInfo("Manifest class path entries must be relative (J2EE 1.4 Section 8.2): path=" + path, moduleBaseUri, classpath, exclusions)));
343 return;
344 }
345
346 URI targetUri = moduleBaseUri.resolve(pathUri);
347 if (targetUri.getPath().endsWith("/")) {
348 problems.add(new DeploymentException(printInfo("target path must not end with a '/' character: path=" + path + ", resolved to targetURI=" + targetUri, moduleBaseUri, classpath, exclusions)));
349 return;
350 }
351 String targetEntry = targetUri.toString();
352 if (exclusions.contains(targetEntry)) {
353 continue;
354 }
355 URI resolvedUri = resolutionUri.resolve(targetUri);
356 String classpathEntry = resolvedUri.toString();
357 //don't get caught in circular references
358 if (classpath.contains(classpathEntry)) {
359 continue;
360 }
361 classpath.add(classpathEntry);
362
363 JarFile classPathJarFile;
364 try {
365 classPathJarFile = factory.newJarFile(targetUri);
366 } catch (IOException e) {
367 problems.add(new DeploymentException(printInfo("Manifest class path entries must be a valid jar file (JAVAEE 5 Section 8.2): path=" + path + ", resolved to targetURI=" + targetUri, moduleBaseUri, classpath, exclusions), e));
368 return;
369 }
370
371 getCompleteManifestClassPath(classPathJarFile, targetUri, resolutionUri, classpath, exclusions, factory, problems);
372 }
373 }
374
375 private String printInfo(String message, URI moduleBaseUri, ClassPathList classpath, ModuleList exclusions) {
376 StringBuffer buf = new StringBuffer(message).append("\n");
377 buf.append(" looking at: ").append(moduleBaseUri);
378 buf.append(" current classpath: ").append(classpath);
379 buf.append(" ignoring modules: ").append(exclusions);
380 return buf.toString();
381 }
382
383 /**
384 * Import the classpath from a jar file's manifest. The imported classpath
385 * is crafted relative to <code>moduleBaseUri</code>.
386 *
387 * @param moduleFile the jar file from which the manifest is obtained.
388 * @param moduleBaseUri the base for the imported classpath
389 * @throws DeploymentException if there is a problem with the classpath in
390 * the manifest
391 */
392 public void addManifestClassPath(JarFile moduleFile, URI moduleBaseUri) throws DeploymentException {
393 Manifest manifest;
394 try {
395 manifest = moduleFile.getManifest();
396 } catch (IOException e) {
397 throw new DeploymentException("Could not read manifest: " + moduleBaseUri);
398 }
399
400 if (manifest == null) {
401 return;
402 }
403 String manifestClassPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
404 if (manifestClassPath == null) {
405 return;
406 }
407
408 for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
409 String path = tokenizer.nextToken();
410
411 URI pathUri;
412 try {
413 pathUri = new URI(path);
414 } catch (URISyntaxException e) {
415 throw new DeploymentException("Invalid manifest classpath entry: module=" + moduleBaseUri + ", path=" + path);
416 }
417
418 if (!pathUri.getPath().endsWith(".jar")) {
419 throw new DeploymentException("Manifest class path entries must end with the .jar extension (J2EE 1.4 Section 8.2): module=" + moduleBaseUri);
420 }
421 if (pathUri.isAbsolute()) {
422 throw new DeploymentException("Manifest class path entries must be relative (J2EE 1.4 Section 8.2): moduel=" + moduleBaseUri);
423 }
424
425 try {
426 URI targetUri = moduleBaseUri.resolve(pathUri);
427 if (targetUri.getPath().endsWith("/"))
428 throw new IllegalStateException("target path must not end with a '/' character: " + targetUri);
429 configuration.addToClassPath(targetUri.toString());
430 } catch (IOException e) {
431 throw new DeploymentException(e);
432 }
433 }
434 }
435
436 public void addClass(URI targetPath, String fqcn, byte[] bytes) throws IOException, URISyntaxException {
437 if (!targetPath.getPath().endsWith("/"))
438 throw new IllegalStateException("target path must end with a '/' character: " + targetPath);
439
440 String classFileName = fqcn.replace('.', '/') + ".class";
441
442 File targetFile = getTargetFile(new URI(targetPath.toString() + classFileName));
443 addFile(targetFile, new ByteArrayInputStream(bytes));
444
445 configuration.addToClassPath(targetPath.toString());
446 }
447
448 public void addFile(URI targetPath, ZipFile zipFile, ZipEntry zipEntry) throws IOException {
449 resourceContext.addFile(targetPath, zipFile, zipEntry);
450 }
451
452 public void addFile(URI targetPath, URL source) throws IOException {
453 resourceContext.addFile(targetPath, source);
454 }
455
456 public void addFile(URI targetPath, File source) throws IOException {
457 resourceContext.addFile(targetPath, source);
458 }
459
460 public void addFile(URI targetPath, String source) throws IOException {
461 resourceContext.addFile(targetPath, source);
462 }
463
464 private void addFile(File targetFile, InputStream source) throws IOException {
465 targetFile.getParentFile().mkdirs();
466 OutputStream out = null;
467 try {
468 out = new FileOutputStream(targetFile);
469 int count;
470 while ((count = source.read(buffer)) > 0) {
471 out.write(buffer, 0, count);
472 }
473 } finally {
474 DeploymentUtil.close(out);
475 }
476 }
477
478 public File getTargetFile(URI targetPath) {
479 return resourceContext.getTargetFile(targetPath);
480 }
481
482 public ClassLoader getClassLoader() throws DeploymentException {
483 return configuration.getConfigurationClassLoader();
484 }
485
486 public Configuration getConfiguration() {
487 return configuration;
488 }
489
490 public void flush() throws IOException {
491 resourceContext.flush();
492 }
493
494 public void close() throws IOException, DeploymentException {
495 if (configurationManager != null) {
496 try {
497 configurationManager.unloadConfiguration(configuration.getId());
498 } catch (NoSuchConfigException ignored) {
499 //ignore
500 }
501 }
502 }
503
504 public void addChildConfiguration(String moduleName, ConfigurationData configurationData) {
505 childConfigurationDatas.put(moduleName, configurationData);
506 }
507
508 public ConfigurationData getConfigurationData() throws DeploymentException {
509 List<String> failures = verify(configuration);
510 if (!failures.isEmpty()) {
511 StringBuffer message = new StringBuffer();
512 for (String failure : failures) {
513 if (message.length() > 0) message.append("\n");
514 message.append(failure);
515 }
516 throw new DeploymentException(message.toString());
517 }
518
519 ArrayList<GBeanData> gbeans = new ArrayList<GBeanData>(configuration.getGBeans().values());
520 Collections.sort(gbeans, new GBeanData.PriorityComparator());
521 ConfigurationData configurationData = new ConfigurationData(configuration.getModuleType(),
522 new LinkedHashSet<String>(configuration.getClassPath()),
523 gbeans,
524 childConfigurationDatas,
525 configuration.getEnvironment(),
526 baseDir,
527 inPlaceConfigurationDir,
528 naming);
529
530 for (ConfigurationData ownedConfiguration : additionalDeployment) {
531 configurationData.addOwnedConfigurations(ownedConfiguration.getId());
532 }
533
534 return configurationData;
535 }
536
537 public void addAdditionalDeployment(ConfigurationData configurationData) {
538 additionalDeployment.add(configurationData);
539 }
540
541 public List getAdditionalDeployment() {
542 return additionalDeployment;
543 }
544
545 public AbstractName getModuleName() {
546 return moduleName;
547 }
548
549 public List<String> verify(Configuration configuration) throws DeploymentException {
550 List<String> failures = new ArrayList<String>();
551 for (Map.Entry<AbstractName, GBeanData> entry : this.configuration.getGBeans().entrySet()) {
552 AbstractName name = entry.getKey();
553 GBeanData gbean = entry.getValue();
554
555 for (Map.Entry<String, ReferencePatterns> referenceEntry : gbean.getReferences().entrySet()) {
556 String referenceName = referenceEntry.getKey();
557 ReferencePatterns referencePatterns = referenceEntry.getValue();
558
559 String failure = verifyReference(gbean, referenceName, referencePatterns, configuration);
560 if (failure != null) {
561 failures.add(failure);
562 }
563 }
564
565 for (ReferencePatterns referencePatterns : gbean.getDependencies()) {
566 String failure = verifyDependency(name, referencePatterns, configuration);
567 if (failure != null) {
568 failures.add(failure);
569 }
570 }
571 }
572 return failures;
573 }
574
575 private String verifyReference(GBeanData gbean, String referenceName, ReferencePatterns referencePatterns, Configuration configuration) {
576 GReferenceInfo referenceInfo = gbean.getGBeanInfo().getReference(referenceName);
577
578 // if there is no reference info we can't verify
579 if (referenceInfo == null) return null;
580
581 // A collection valued reference doesn't need to be verified
582 if (referenceInfo.getProxyType().equals(Collection.class.getName())) return null;
583
584 String message = isVerifyReference(referencePatterns, configuration);
585 if (message != null) {
586 return "Unable to resolve reference \"" + referenceName + "\" in gbean " +
587 gbean.getAbstractName() + " to a gbean matching the pattern " + referencePatterns.getPatterns() + "due to: " + message;
588 }
589 return null;
590 }
591
592 private String verifyDependency(AbstractName name, ReferencePatterns referencePatterns, Configuration configuration) {
593 String message = isVerifyReference(referencePatterns, configuration);
594 if (message != null) {
595 return "Unable to resolve dependency in gbean " + name +
596 " to a gbean matching the pattern " + referencePatterns.getPatterns() + "due to: " + message;
597 }
598
599 return null;
600 }
601
602 private String isVerifyReference(ReferencePatterns referencePatterns, Configuration configuration) {
603 // we can't verify a resolved reference since it will have a specific artifact already set...
604 // hopefully the deployer won't generate bad resolved references
605 if (referencePatterns.isResolved()) return null;
606
607 // Do not verify the reference if it has an explicit depenency on another artifact, because it it likely
608 // that the other artifact is not in the "environment" (if it were you wouldn't use the long form)
609 Set<AbstractNameQuery> patterns = referencePatterns.getPatterns();
610 for (AbstractNameQuery query : patterns) {
611 if (query.getArtifact() != null) return null;
612 }
613
614 // attempt to find the bean
615 try {
616 configuration.findGBean(patterns);
617 return null;
618 } catch (GBeanNotFoundException e) {
619 //TODO bug!! GERONIMO-3140 Multiple matches may be caused by using an already-loaded configuration rather than reloading one
620 // using the client_artifact_aliases.properties which e.g. remap the server tm to the client tm.
621 if (e.hasMatches()) {
622 return null;
623 }
624 return e.getMessage();
625 }
626 }
627 }