/* | |
* 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.felix.ipojo.handler.eventadmin.test.donut; | |
import org.osgi.service.event.Event; | |
import org.osgi.service.event.EventHandler; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Implementation of a donut consumer. | |
* | |
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> | |
* @see Homer Simpson | |
*/ | |
public class EventConsumerImpl implements DonutConsumer, EventHandler { | |
/** | |
* The name of the donut consumer. | |
*/ | |
private String m_name; | |
/** | |
* The list of eaten donuts. | |
*/ | |
private List m_donuts = new ArrayList(); | |
/** | |
* Is this consumer a slow eater ? | |
*/ | |
private boolean m_isSlow; | |
/** | |
* Utility method that causes the current thread to sleep. | |
* | |
* @param millis the number of milliseconds to wait | |
*/ | |
public static void sleep(long millis) { | |
long past = System.currentTimeMillis(); | |
long future = past + millis; | |
long now = past; | |
while (now < future) { | |
try { | |
Thread.sleep(future - now); | |
} catch (Exception e) { | |
} | |
now = System.currentTimeMillis(); | |
} | |
} | |
/** | |
* Process incoming donuts. This method is called by the receiveDonut | |
* callback. | |
* | |
* @param donut the received donut | |
*/ | |
private void doReceiveDonut(Donut donut) { | |
synchronized (m_donuts) { | |
m_donuts.add(donut); | |
m_donuts.notify(); | |
} | |
} | |
/** | |
* Donut receiver callback. This method is called when a donut is received | |
* on the listened topic. | |
* | |
* @param donut the received donut | |
*/ | |
public void receiveDonut(Donut donut) { | |
final Donut myDonut = donut; | |
if (m_isSlow) { | |
new Thread(new Runnable() { | |
public void run() { | |
sleep(DonutConsumerImpl.BLACK_LIST_TIME); | |
doReceiveDonut(myDonut); | |
} | |
}, m_name + " eating " + donut).start(); | |
} else { | |
doReceiveDonut(donut); | |
} | |
} | |
/** | |
* Event donut receiver callback. This method is called when an event is | |
* received on the listened topic. | |
* | |
* @param event the received event | |
*/ | |
public void receiveEvent(Event event) { | |
Object thing = event.getProperty("food"); | |
if (Donut.class.isInstance(thing)) { | |
receiveDonut((Donut) thing); | |
} else { | |
// Nothing to do. | |
} | |
} | |
/** | |
* Event receiver callback. This method is called by the event admin service | |
* when a event is received. | |
* | |
* @param event the received event | |
*/ | |
public void handleEvent(Event event) { | |
receiveEvent(event); | |
} | |
/** | |
* Clear the eaten donuts list. (Useful before tests) | |
*/ | |
public void clearDonuts() { | |
synchronized (m_donuts) { | |
m_donuts.clear(); | |
} | |
} | |
/** | |
* Get the first received donut and remove it from the eaten donut list. | |
* | |
* @return the first received donut or null if no donut is available | |
*/ | |
public Donut getDonut() { | |
Donut donut = null; | |
synchronized (m_donuts) { | |
if (!m_donuts.isEmpty()) { | |
donut = (Donut) m_donuts.remove(0); | |
} | |
} | |
return donut; | |
} | |
/** | |
* Get the whole list of eaten donuts. | |
* | |
* @return the array containing all eaten donuts | |
*/ | |
public Donut[] getAllDonuts() { | |
Donut[] donuts = new Donut[0]; | |
synchronized (m_donuts) { | |
donuts = (Donut[]) m_donuts.toArray(donuts); | |
m_donuts.clear(); | |
} | |
return donuts; | |
} | |
/** | |
* Get the first donut if available or wait for an incoming donut. The | |
* returned donut is removed from the eaten donut list. | |
* | |
* @return the first available donut. | |
*/ | |
public Donut waitForDonut() { | |
Donut donut = null; | |
synchronized (m_donuts) { | |
while (donut == null) { | |
if (m_donuts.isEmpty()) { | |
try { | |
m_donuts.wait(); | |
} catch (InterruptedException e) { | |
// Thanks Checkstyle to forbid empty catch statements | |
// ;-( | |
} | |
} else { | |
donut = (Donut) m_donuts.remove(0); | |
} | |
} | |
} | |
return donut; | |
} | |
/** | |
* Return the size of the eaten donut list. | |
* | |
* @return the size of the eaten donut list | |
*/ | |
public int getNumberOfDonuts() { | |
int length; | |
synchronized (m_donuts) { | |
length = m_donuts.size(); | |
} | |
return length; | |
} | |
} |