Package org.apache.tuscany.sca.binding.notification

Source Code of org.apache.tuscany.sca.binding.notification.NotificationReferenceBindingInvoker$SubscriberInfo

/*
* 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.tuscany.sca.binding.notification;

import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.axiom.om.OMElement;
import org.apache.tuscany.sca.binding.notification.encoding.BrokerID;
import org.apache.tuscany.sca.binding.notification.encoding.Constants;
import org.apache.tuscany.sca.binding.notification.encoding.EncodingUtils;
import org.apache.tuscany.sca.binding.notification.encoding.EndpointReference;
import org.apache.tuscany.sca.binding.notification.util.IOUtils;
import org.apache.tuscany.sca.binding.notification.util.IOUtils.IOUtilsException;
import org.apache.tuscany.sca.binding.notification.util.IOUtils.Writeable;
import org.apache.tuscany.sca.implementation.notification.ImmutableMessage;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;

/**
* Turns invoke into remote message fan-out
*
* @version $Rev$ $Date$
*/
public class NotificationReferenceBindingInvoker implements Invoker {

    private static final Message RESPONSE = new ImmutableMessage();
    private Operation operation;
   
    private List<SubscriberInfo> subscribers;
    private String brokerID;

    public NotificationReferenceBindingInvoker(Operation operation) {
        this.operation = operation;
        this.subscribers = new ArrayList<SubscriberInfo>();
        this.brokerID = null;
    }
   
    public void setBrokerID(String brokerID) {
        this.brokerID = brokerID;
    }
   
    public String getBrokerID() {
        return brokerID;
    }
   
    public Message invoke(Message msg) {
        Object payload = msg.getBody();
        if (payload == null) {
            throw new RuntimeException("Message body is null");
        }
        Writeable writeable = null;
        String incomingBrokerID = null;
        if (payload.getClass().isArray()) {
            Object[] bodyArray = (Object[])payload;
            if (bodyArray.length == 3) {
                writeable = getWriteableFromByteArray((byte[])bodyArray[1]);
                incomingBrokerID = (String)bodyArray[2];
            }
            else if (bodyArray.length == 1) {
                writeable = getWriteableFromPayload(bodyArray[0]);
            }
            else {
                throw new RuntimeException("Invalid body array size");
            }
        }
        else {
            writeable = getWriteableFromPayload(payload);
        }

        try {
            synchronized(this) {
                for (SubscriberInfo subscriber : subscribers) {
                    // check for each subscriber's broker id and skip if equal
                    if (incomingBrokerID != null && subscriber.brokerID != null && incomingBrokerID.equals(subscriber.brokerID)) {
                        continue;
                    }
                    HashMap<String, String> headers = new HashMap<String, String>();
                    headers.put(IOUtils.Notification_Operation, operation.getName());
                    if (brokerID != null) {
                        headers.put(Constants.Broker_ID, brokerID);
                    }
                    IOUtils.sendHttpRequest(subscriber.address, headers, writeable, null);
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Sender caught exception", e);
        }
        return RESPONSE;
    }
   
    private Writeable getWriteableFromPayload(Object payload) throws RuntimeException {
        if (!(payload instanceof OMElement)) {
            throw new RuntimeException("payload not OMElement");
        }
        final OMElement element = (OMElement)payload;
        Writeable writeable = new Writeable() {
            public void write(OutputStream os) throws IOUtilsException {
                try {
                    element.serialize(os);
                    os.flush();
                }
                catch(Exception e) {
                    throw new IOUtilsException(e);
                }
            }
        };
        return writeable;
    }

    private Writeable getWriteableFromByteArray(final byte[] payload) {
        Writeable writeable = new Writeable() {
            public void write(OutputStream os) throws IOUtilsException {
                try {
                    os.write(payload);
                    os.flush();
                }
                catch(Exception e) {
                    throw new IOUtilsException(e);
                }
            }
        };
        return writeable;
    }
   
    public void addSubscriberUrl(URL subscriberUrl) {
        addSubscriber(subscriberUrl, null);
    }
   
    public void addSubscriber(EndpointReference subscriberEPR) {
        BrokerID brokerID = null;
        if (subscriberEPR.getReferenceProperties() != null) {
            brokerID = subscriberEPR.getReferenceProperties().getProperty(BrokerID.class);
        }
        addSubscriber(subscriberEPR.getEndpointAddress().getAddress(), (brokerID != null ? brokerID.getID() : null));
    }

    public void addSubscriber(URL address, String brokerID) {
        synchronized(this) {
            SubscriberInfo si = new SubscriberInfo(address);
            si.brokerID = brokerID;
            if (subscribers == null) {
                subscribers = new ArrayList<SubscriberInfo>();
            }
            subscribers.add(si);
        }
    }
   
    public void replaceSubscribers(EndpointReference brokerConsumerEPR) {
        synchronized(this) {
            subscribers = null;
        }
        addSubscriber(brokerConsumerEPR);
    }
   
    public void replaceBrokerSubscriber(URL removedBrokerConsumerUrl, EndpointReference chosenBrokerConsumerEpr) {
        synchronized(this) {
            if (subscribers == null) {
                throw new RuntimeException("No subscribers");
            }
            SubscriberInfo siToRemove = null;
            for (SubscriberInfo si : subscribers) {
                if (si.address.equals(removedBrokerConsumerUrl)) {
                    siToRemove = si;
                }
            }
            if (siToRemove == null) {
                throw new RuntimeException("Can't find info for broker to remove [" + removedBrokerConsumerUrl + "]");
            }
            if (!subscribers.remove(siToRemove)) {
                throw new RuntimeException("Can't remove info for [" + siToRemove.address + "]");
            }
        }
        if (chosenBrokerConsumerEpr != null) {
            addSubscriber(chosenBrokerConsumerEpr);
        }
    }
   
    public List<EndpointReference> getNeighborBrokerConsumerEprs() {
        synchronized(this) {
            if (subscribers == null) {
                throw new RuntimeException("No subscribers");
            }
            List<EndpointReference> neighborBrokerConsumerEprs = new ArrayList<EndpointReference>();
            for(SubscriberInfo si : subscribers) {
                if (si.brokerID != null) {
                    neighborBrokerConsumerEprs.add(EncodingUtils.createEndpointReference(si.address, si.brokerID));
                }
            }
           
            return neighborBrokerConsumerEprs;
        }
    }
   
    public void removeBrokerSubscribers() {
        synchronized(this) {
            if (subscribers == null) {
                throw new RuntimeException("No subscribers");
            }
            List<SubscriberInfo> sisToRemove = new ArrayList<SubscriberInfo>();
            for (SubscriberInfo si : subscribers) {
                if (si.brokerID != null) {
                    sisToRemove.add(si);
                }
            }
            for(SubscriberInfo si : sisToRemove) {
                if (!subscribers.remove(si)) {
                    throw new RuntimeException("Can't remove broker subscriber [" + si.address + "]");
                }
            }
        }
    }
   
    class SubscriberInfo {
        public URL address;
        public String brokerID;
       
        public SubscriberInfo(URL address) {
            this.address = address;
            this.brokerID = null;
        }
    }
}
TOP

Related Classes of org.apache.tuscany.sca.binding.notification.NotificationReferenceBindingInvoker$SubscriberInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.