/**
* 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.yoko.bindings.corba;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.Destination;
import org.apache.cxf.transport.MessageObserver;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.schemas.yoko.bindings.corba.AddressType;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManager;
public class CorbaDestination implements Destination {
private static final Logger LOG = LogUtils.getL7dLogger(CorbaDestination.class);
private AddressType address;
private EndpointReferenceType reference;
private ORB orb;
private BindingInfo binding;
private EndpointInfo endpointInfo;
private OrbConfig orbConfig;
public CorbaDestination(EndpointInfo ei, OrbConfig config) {
address = ei.getExtensor(AddressType.class);
binding = ei.getBinding();
reference = new EndpointReferenceType();
AttributedURIType addr = new AttributedURIType();
addr.setValue(address.getLocation());
reference.setAddress(addr);
endpointInfo = ei;
orbConfig = config;
}
public EndpointReferenceType getAddress() {
return reference;
}
public Conduit getBackChannel(Message inMessage,
Message partialResponse,
EndpointReferenceType ref)
throws IOException {
return new CorbaServerConduit(endpointInfo, reference, orbConfig);
}
public BindingInfo getBindingInfo() {
return binding;
}
public EndpointInfo getEndPointInfo() {
return endpointInfo;
}
public void shutdown() {
if (orb != null) {
try {
orb.destroy();
} catch (Exception ex) {
LOG.log(Level.SEVERE, "Couldn't shutdown the corba destination. Failed to destroy orb");
throw new CorbaBindingException(ex);
}
}
}
protected ORB getOrb() {
return orb;
}
protected AddressType getAddressType() {
return address;
}
public synchronized void setMessageObserver(MessageObserver observer) {
String location = address.getLocation();
LOG.info("Service address retrieved: " + location);
// TODO: Get any configuration options for the ORB and set the appropriate properties.
java.util.Properties props = System.getProperties();
props.put("org.omg.CORBA.ORBClass", orbConfig.getOrbClass());
props.put("org.omg.CORBA.ORBSingletonClass", orbConfig.getOrbSingletonClass());
props.put("yoko.orb.id", "Yoko-Server-Binding");
// If we have one of these two types of addresses, we should specify the address
// and port information as properties to the ORB during initialization.
if (location.startsWith("IOR:")) {
// TODO: How to handle this? Can we obtain port/host information from the IOR
// or do we just want to let the ORB pick the port and export the IOR to the
// Logs?
} else if (location.startsWith("corbaloc")) {
int corbalocIndex = location.indexOf(":");
int protocolIndex = location.indexOf(":", corbalocIndex + 1);
String protocol = location.substring(corbalocIndex + 1, protocolIndex);
int hostIndex = location.indexOf(":", protocolIndex + 1);
String host = location.substring(protocolIndex + 1, hostIndex);
// the port number should be followed by a '/' character
int portIndex = location.indexOf("/", hostIndex + 1);
String port = location.substring(hostIndex + 1, portIndex);
if (protocol.length() == 0) {
// This means no protocol was defined. Default to iiop
protocol = "iiop";
}
props.put("yoko.orb.oa.endpoint", new String(protocol + " --host " + host + " --port " + port));
LOG.info("Set server endpoint: " + protocol + " --host " + host + " --port " + port);
}
List<String> orbArgs = orbConfig.getOrbArgs();
orb = ORB.init(orbArgs.toArray(new String[orbArgs.size()]), props);
activate(observer);
}
public void activate(MessageObserver observer) {
// Get the address that the DSI servant should be publishing
String location = address.getLocation();
org.omg.CORBA.Object obj = null;
try {
POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
POAManager poaManager = rootPOA.the_POAManager();
Policy[] policies = new Policy[3];
policies[0] = rootPOA
.create_lifespan_policy(
org.omg.PortableServer.LifespanPolicyValue.PERSISTENT);
policies[1] = rootPOA
.create_implicit_activation_policy(
org.omg.PortableServer.ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION);
policies[2] = rootPOA
.create_id_uniqueness_policy(
org.omg.PortableServer.IdUniquenessPolicyValue.UNIQUE_ID);
POA bindingPOA = rootPOA.create_POA("BindingPOA", poaManager, policies);
// CorbaDSIServant servant = new CorbaDSIServant(orb, bindingPOA, this, observer);
CorbaDSIServant servant = new CorbaDSIServant();
servant.init(orb, bindingPOA, this, observer);
byte[] objectId = bindingPOA.activate_object(servant);
obj = bindingPOA.id_to_reference(objectId);
// Register the object reference so we can support passing references as
// parameters and return types. Note that we need the actual endpoint that
// this object reference has been created on. This is available through the
// endpointInfo object passed during construction.
CorbaObjectReferenceHelper.addReference(endpointInfo.getAddress(), obj);
if (location.startsWith("relfile:")) {
String iorFile = location.substring("relfile:".length(), location.length());
// allow for up to 3 '/' to match common uses of relfile url format
for (int n = 0; n < 3; n++) {
if (iorFile.charAt(0) != '/') {
break;
} else {
iorFile = iorFile.substring(1);
}
}
CorbaUtils.exportObjectReferenceToFile(obj, orb, iorFile);
} else if (location.startsWith("file:")) {
String iorFile = location.substring("file:".length(), location.length());
// allow for up to 3 '/' to match common uses of file url format
for (int n = 0; n < 3; n++) {
if (iorFile.charAt(0) != '/') {
break;
} else {
iorFile = iorFile.substring(1);
}
}
// to match the ORB, file must have complete path information, therefore we add
// a '/' prefix to the address
//iorFile = "/" + iorFile;
CorbaUtils.exportObjectReferenceToFile(obj, orb, iorFile);
} else if (location.startsWith("corbaloc")) {
// Try add the key to the boot manager. This is required for a corbaloc
try {
int keyIndex = location.indexOf('/');
String key = location.substring(keyIndex + 1);
org.apache.yoko.orb.OB.BootManager bootManager =
org.apache.yoko.orb.OB.BootManagerHelper.narrow(
orb.resolve_initial_references("BootManager"));
bootManager.add_binding(key.getBytes(), obj);
LOG.info("Added key " + key + " to bootmanager");
} catch (Exception ex) {
// TODO: Continue without for now
}
String ior = orb.object_to_string(obj);
address.setLocation(ior);
String iorFile = "endpoint.ior";
CorbaUtils.exportObjectReferenceToFile(obj, orb, iorFile);
} else {
String ior = orb.object_to_string(obj);
address.setLocation(ior);
String iorFile = "endpoint.ior";
CorbaUtils.exportObjectReferenceToFile(obj, orb, iorFile);
LOG.info("Object Reference: " + orb.object_to_string(obj));
}
// TODO: Provide other export mechanisms?
poaManager.activate();
} catch (Exception ex) {
// TODO: Throw appropriate exception
throw new CorbaBindingException("Unable to activate CORBA servant", ex);
}
}
}