Java tutorial
/* * Generated by the Mule project wizard. http://mule.mulesource.org * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.transport.comm; import org.mule.transport.AbstractMessageReceiver; import org.mule.transport.ConnectException; import org.mule.transport.AbstractReceiverResourceWorker; import org.mule.transport.comm.i18n.CommMessages; import org.mule.api.transport.Connector; import org.mule.api.service.Service; import org.mule.api.endpoint.InboundEndpoint; import org.mule.api.lifecycle.CreateException; import org.mule.api.lifecycle.DisposeException; import org.mule.api.lifecycle.Disposable; import org.mule.api.MuleException; import org.mule.api.transaction.Transaction; import org.mule.api.transaction.TransactionException; import org.mule.api.retry.RetryCallback; import org.mule.api.retry.RetryContext; import org.mule.config.i18n.CoreMessages; import org.mule.util.monitor.Expirable; import org.mule.DefaultMuleMessage; import org.apache.commons.validator.GenericValidator; import javax.resource.spi.work.Work; import javax.resource.spi.work.WorkManager; import javax.resource.spi.work.WorkException; import javax.comm.CommPort; import java.net.*; import java.io.*; import java.util.List; import java.util.Iterator; import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit; /** * Created by IntelliJ IDEA. * User: Christopher Cheng * Date: Mar 1, 2009 * Time: 4:16:42 PM * To change this template use File | Settings | File Templates. */ public class CommMessageReceiver extends AbstractMessageReceiver implements Work { private CommPort commPort = null; public CommMessageReceiver(Connector connector, Service service, InboundEndpoint endpoint) throws CreateException { super(connector, service, endpoint); } protected void doConnect() throws ConnectException { disposing.set(false); URI uri = endpoint.getEndpointURI().getUri(); try { int baudrate = 9600; int databits = 8; int stopbits = 1; int parity = 0; int delay = 150; String host = ""; if (GenericValidator.isInt((String) endpoint.getProperties().get("baudrate"))) { baudrate = Integer.valueOf((String) endpoint.getProperties().get("baudrate")); } if (GenericValidator.isInt((String) endpoint.getProperties().get("databits"))) { databits = Integer.valueOf((String) endpoint.getProperties().get("databits")); } if (GenericValidator.isInt((String) endpoint.getProperties().get("stopbits"))) { stopbits = Integer.valueOf((String) endpoint.getProperties().get("stopbits")); } if (GenericValidator.isInt((String) endpoint.getProperties().get("parity"))) { parity = Integer.valueOf((String) endpoint.getProperties().get("parity")); } host = uri.getHost(); commPort = ((CommConnector) connector).getCommPort(host, baudrate, databits, stopbits, parity, delay); } catch (Exception e) { throw new org.mule.transport.ConnectException(CommMessages.failedToBindToUri(uri), e, this); } try { getWorkManager().scheduleWork(this, WorkManager.INDEFINITE, null, connector); } catch (WorkException e) { throw new ConnectException(CoreMessages.failedToScheduleWork(), e, this); } } protected void doDisconnect() throws ConnectException { // this will cause the server thread to quit disposing.set(true); try { if (commPort != null) { if (logger.isDebugEnabled()) { logger.debug("Closing: " + commPort); } commPort.close(); } } catch (Exception e) { logger.warn("Failed to close server port: " + e.getMessage(), e); } } protected void doStart() throws MuleException { // nothing to do } protected void doStop() throws MuleException { // nothing to do } /** * Obtain the serverSocket * @return the server socket for this server */ public CommPort getCommPort() { return commPort; } public void run() { System.out.println("CommMessageReceiver run"); // while (!disposing.get()) // { if (connector.isStarted() && !disposing.get()) { try { retryTemplate.execute(new RetryCallback() { public void doWork(RetryContext context) throws Exception { // CommPort commPort = this.commPort; try { // commPort = commPort.accept(); } catch (Exception e) { if (!connector.isDisposed() && !disposing.get()) { throw new ConnectException(e, null); } } if (commPort != null) { Work work = createWork(commPort); getWorkManager().scheduleWork(work, WorkManager.INDEFINITE, null, connector); } } public String getWorkDescription() { return getConnectionDescription(); } }, getWorkManager()); } catch (Exception e) { handleException(e); } } // } } public void release() { // template method } protected void doDispose() { try { if (commPort != null) { if (logger.isDebugEnabled()) { logger.debug("Closing: " + commPort); } commPort.close(); } commPort = null; } catch (Exception e) { logger.error(new DisposeException(CommMessages.failedToCloseSocket(), e, this)); } logger.info("Closed Tcp port"); } protected Work createWork(CommPort port) throws IOException { return new CommWorker(port, this); } protected class CommWorker extends AbstractReceiverResourceWorker implements Disposable, Expirable { protected CommPort commPort = null; protected CommInputStream dataIn; protected InputStream underlyingIn; protected OutputStream dataOut; protected CommProtocol protocol; protected boolean dataInWorkFinished = false; protected Object notify = new Object(); private boolean moreMessages = true; public CommWorker(CommPort commPort, AbstractMessageReceiver receiver) throws IOException { super(commPort, receiver, ((CommConnector) connector).getCommProtocol().createResponse(commPort)); this.commPort = commPort; final CommConnector tcpConnector = ((CommConnector) connector); protocol = tcpConnector.getCommProtocol(); try { tcpConnector.configurePort(CommConnector.SERVER, commPort); underlyingIn = new BufferedInputStream(commPort.getInputStream()); dataIn = new CommInputStream(underlyingIn) { public void close() throws IOException { // Don't actually close the stream, we just want to know if the // we want to stop receiving messages on this sockete. // The Protocol is responsible for closing this. dataInWorkFinished = true; moreMessages = false; synchronized (notify) { notify.notifyAll(); } } }; dataOut = new BufferedOutputStream(commPort.getOutputStream()); } catch (IOException e) { logger.error("Failed to set Port properties: " + e.getMessage(), e); } } public void expired() { dispose(); } public void dispose() { releasePort(); } public void release() { waitForStreams(); releasePort(); } private void waitForStreams() { // The Message with the InputStream as a payload can be dispatched // into a different thread, in which case we need to wait for it to // finish streaming if (!dataInWorkFinished) { synchronized (notify) { if (!dataInWorkFinished) { try { notify.wait(); } catch (InterruptedException e) { } } } } } /** * Releases the socket when the input stream is closed. */ private void releasePort() { try { if (commPort != null) { if (logger.isDebugEnabled()) { // some dirty workaround for IBM JSSE's SSL implementation, // which closes sockets asynchronously by that point. String name = commPort.getName(); // final SocketAddress socketAddress = commPort.getLocalSocketAddress(); if (name == null) { logger.debug("Listener has already been closed by other process."); } else { logger.debug("Closing listener: " + name); // logger.debug("Closing listener: " + socketAddress); } } shutdownPort(); commPort.close(); } } catch (IOException e) { logger.warn("Socket close failed with: " + e); } } protected void shutdownPort() throws IOException { try { // todo check if commPort needs to do this // commPort.shutdownOutput(); } catch (UnsupportedOperationException e) { //Ignore, not supported by ssl sockets } } protected void bindTransaction(Transaction tx) throws TransactionException { //nothing to do } protected Object getNextMessage(Object resource) throws Exception { long keepAliveTimeout = ((CommConnector) connector).getKeepAliveTimeout(); Object readMsg = null; try { // Create a monitor if expiry was set if (keepAliveTimeout > 0) { ((CommConnector) connector).getKeepAliveMonitor().addExpirable(keepAliveTimeout, TimeUnit.MILLISECONDS, this); } readMsg = protocol.read(dataIn); // There was some action so we can clear the monitor ((CommConnector) connector).getKeepAliveMonitor().removeExpirable(this); if (dataIn.isStreaming()) { moreMessages = false; } return readMsg; } catch (SocketTimeoutException e) { ((CommConnector) connector).getKeepAliveMonitor().removeExpirable(this); } finally { if (readMsg == null) { // Protocols can return a null object, which means we're done // reading messages for now and can mark the stream for closing later. // Also, exceptions can be thrown, in which case we're done reading. dataIn.close(); } } return null; } protected boolean hasMoreMessages(Object message) { return !dataInWorkFinished && !disposing.get() && moreMessages; } //@Override protected void handleResults(List messages) throws Exception { //should send back only if remote synch is set or no outbound endpoints if (endpoint.isRemoteSync() || !service.getOutboundRouter().hasEndpoints()) { for (Iterator iterator = messages.iterator(); iterator.hasNext();) { Object o = iterator.next(); protocol.write(dataOut, o); dataOut.flush(); } } } protected void preRouteMuleMessage(final DefaultMuleMessage message) throws Exception { super.preRouteMuleMessage(message); // tod there's no remote address? // final SocketAddress clientAddress = commPort.getRemoteSocketAddress(); // if (clientAddress != null) // { // message.setProperty(MuleProperties.MULE_REMOTE_CLIENT_ADDRESS, clientAddress.toString()); // } } } }