blob: 973afb4deeac10a004562d983214b96ad1b0f640 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.assembler.classic;
import org.apache.openejb.util.LinkResolver;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Arrays;
import java.util.ArrayList;
/**
* @version $Rev: 1303612 $ $Date: 2012-03-21 22:59:11 +0000 (Wed, 21 Mar 2012) $
*/
public class EjbResolver {
public static interface Reference {
String getName();
Type getRefType();
String getHome();
String getInterface();
String getMappedName();
String getEjbLink();
}
public static enum Type {
UNKNOWN, LOCAL, REMOTE;
}
public static enum Scope {
GLOBAL, EAR, EJBJAR;
}
private final Map<String, EnterpriseBeanInfo> deployments = new TreeMap<String, EnterpriseBeanInfo>();
private final LinkResolver<String> resolver = new LinkResolver<String>();
private final Map<Interfaces, List<Interfaces>> interfaces = new TreeMap<Interfaces, List<Interfaces>>();
private EjbResolver parent;
private final Scope scope;
public EjbResolver(EjbResolver parent, Scope scope, EjbJarInfo... ejbJars) {
this(parent, scope, Arrays.asList(ejbJars));
}
public EjbResolver(EjbResolver parent, Scope scope, List<EjbJarInfo> ejbJars) {
this.scope = scope;
this.parent = parent;
for (EjbJarInfo ejbJarInfo : ejbJars) {
add(ejbJarInfo);
}
}
/**
* Possible syncronization issue here
*/
public void addAll(List<EjbJarInfo> ejbJars) {
for (EjbJarInfo ejbJarInfo : ejbJars) {
add(ejbJarInfo);
}
}
public void add(EjbJarInfo ejbJarInfo) {
for (EnterpriseBeanInfo bean : ejbJarInfo.enterpriseBeans) {
index(ejbJarInfo.moduleUri, bean);
}
}
private void index(URI moduleURI, EnterpriseBeanInfo bean) {
// All deployments: deploymentId -> bean
deployments.put(bean.ejbDeploymentId, bean);
// add to the link resolver
resolver.add(moduleURI, bean.ejbName, bean.ejbDeploymentId);
// Remote: Interfaces(home,object) -> deploymentId
if (bean.remote != null) {
addInterfaces(new Interfaces(bean.home, bean.remote, Type.REMOTE, bean.ejbDeploymentId));
addInterfaces(new Interfaces(bean.remote, Type.REMOTE, bean.ejbDeploymentId));
}
for (String businessRemote : bean.businessRemote) {
addInterfaces(new Interfaces(businessRemote, Type.REMOTE, bean.ejbDeploymentId));
}
// Local: Interfaces(home,object) -> deploymentId
if (bean.local != null) {
addInterfaces(new Interfaces(bean.localHome, bean.local, Type.LOCAL, bean.ejbDeploymentId));
addInterfaces(new Interfaces(bean.local, Type.LOCAL, bean.ejbDeploymentId));
}
for (String businessLocal : bean.businessLocal) {
addInterfaces(new Interfaces(businessLocal, Type.LOCAL, bean.ejbDeploymentId));
}
if (bean.localbean) {
addInterfaces(new Interfaces(bean.ejbClass, Type.LOCAL, bean.ejbDeploymentId));
for (String parent : bean.parents) {
addInterfaces(new Interfaces(parent, Type.LOCAL, bean.ejbDeploymentId));
}
}
}
private void addInterfaces(Interfaces interfaces) {
List<Interfaces> similar = this.interfaces.get(interfaces);
if (similar == null) {
similar = new ArrayList<Interfaces>();
this.interfaces.put(interfaces, similar);
}
similar.add(interfaces);
}
private String resolveLink(String link, URI moduleUri) {
if (link == null || link.length() == 0) return null;
String id = resolver.resolveLink(link, moduleUri);
if (id == null && parent != null) {
id = parent.resolveLink(link, moduleUri);
}
return id;
}
private String resolveInterface(Reference ref) {
String id = null;
if (ref.getInterface() == null) {
// TODO: Support home-only refs. Could only happen for EJB 2.x Entity beans
// All other beans are required to have create methods in their home interfaces
// and we would have used it to discover the remote interface when creating the ref
return null;
}
List<Interfaces> matches = this.interfaces.get(new Interfaces(ref.getHome(), ref.getInterface()));
if (matches != null && matches.size() > 0){
List<Interfaces> nameMatches = filter(matches, ref.getName());
// Imply by name and type (local/remote)
id = first(filter(nameMatches, ref.getRefType()));
if (id == null){
// Match by name
id = first(nameMatches);
}
// Imply by type (local/remote)
if (id == null){
id = first(filter(matches, ref.getRefType()));
}
// Just grab the first
if (id == null){
id = first(matches);
}
}
if (id == null && parent != null) {
id = parent.resolveInterface(ref);
}
return id;
}
private String first(List<Interfaces> list) {
if (list.size() == 0) return null;
return list.get(0).getId();
}
private List<Interfaces> filter(List<Interfaces> list, String name) {
String shortName = name.replaceAll(".*/", "");
List<Interfaces> matches = new ArrayList();
for (Interfaces entry : list) {
if (name.equalsIgnoreCase(entry.getId())){
matches.add(entry);
} else if (shortName.equalsIgnoreCase(entry.getId())){
matches.add(entry);
}
}
return matches;
}
private List<Interfaces> filter(List<Interfaces> list, Type type) {
List<Interfaces> matches = new ArrayList();
for (Interfaces entry : list) {
if (type == Type.UNKNOWN || type == entry.type){
matches.add(entry);
}
}
return matches;
}
public Scope getScope(String deploymentId) {
if (deployments.containsKey(deploymentId)) return scope;
if (parent != null) return parent.getScope(deploymentId);
return null;
}
public EnterpriseBeanInfo getEnterpriseBeanInfo(String deploymentId) {
EnterpriseBeanInfo info = deployments.get(deploymentId);
if (info == null && parent != null) {
info = parent.getEnterpriseBeanInfo(deploymentId);
}
return info;
}
public String resolve(Reference ref, URI moduleUri) {
if (ref.getMappedName() != null && !ref.getMappedName().equals("")) {
return ref.getMappedName();
}
String targetId = this.resolveLink(ref.getEjbLink(), moduleUri);
if (targetId == null && ref.getEjbLink() == null) {
targetId = resolveInterface(ref);
}
return targetId;
}
private static class Interfaces implements Comparable {
private final String id;
private final Type type;
private final String homeInterface;
private final String objectInterface;
public Interfaces(String objectInterface, Type type, String id) {
if (objectInterface == null) throw new NullPointerException("objectInterface is null");
this.homeInterface = "<none>";
this.objectInterface = objectInterface;
this.type = type;
this.id = id;
}
public Interfaces(String homeInterface, String objectInterface, Type type, String id) {
if (homeInterface == null) homeInterface = "<none>";
if (objectInterface == null) throw new NullPointerException("objectInterface is null");
this.homeInterface = homeInterface;
this.objectInterface = objectInterface;
this.type = type;
this.id = id;
}
public Interfaces(String homeInterface, String objectInterface) {
if (homeInterface == null) homeInterface = "<none>";
if (objectInterface == null) throw new NullPointerException("objectInterface is null");
this.homeInterface = homeInterface;
this.objectInterface = objectInterface;
this.type = null;
this.id = null;
}
public String getId() {
return id;
}
public Type getType() {
return type;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Interfaces that = (Interfaces) o;
return homeInterface.equals(that.homeInterface) && objectInterface.equals(that.objectInterface);
}
public int hashCode() {
int result;
result = homeInterface.hashCode();
result = 31 * result + objectInterface.hashCode();
return result;
}
public int compareTo(Object o) {
if (this == o) return 0;
Interfaces that = (Interfaces) o;
return toString().compareTo(that.toString());
}
public String toString() {
return homeInterface + ":" + objectInterface;
}
}
}