/**************************************************************************** * Copyright (c) 2004 Composent, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Composent, Inc. - initial API and implementation *****************************************************************************/ package org.eclipse.ecf.provider.generic; import java.io.*; import java.net.Socket; import java.net.URI; import java.util.*; import org.eclipse.ecf.internal.provider.ProviderPlugin; import org.eclipse.ecf.provider.comm.IConnectRequestHandler; import org.eclipse.ecf.provider.comm.tcp.*; public class SOContainerGroup implements ISocketAcceptHandler { /** * @since 4.7 */ public static final String INVALID_CONNECT = "Invalid connect request."; //$NON-NLS-1$ String name; protected Map map; public SOContainerGroup(String name) { this.name = name; map = Collections.synchronizedMap(new TreeMap()); } public String add(String key, SOContainer aSpace) { if (key == null || aSpace == null) return null; map.put(key, aSpace); return key; } public SOContainer get(String key) { if (key == null) return null; return (SOContainer) map.get(key); } public SOContainer remove(String key) { if (key == null) return null; return (SOContainer) map.remove(key); } public boolean contains(String key) { if (key == null) return false; return map.containsKey(key); } public String getName() { return name; } public Iterator elements() { return map.values().iterator(); } /** * @param aSocket socket * @return ObjectOutputStream new object output stream for socket * @throws IOException if object output stream cannot be created * @since 4.7 */ protected ObjectOutputStream createObjectOutputStream(Socket aSocket) throws IOException { return new ObjectOutputStream(aSocket.getOutputStream()); } /** * @param aSocket socket * @return ObjectInputStream new object input stream for socket * @throws IOException if object input stream cannot be created * @since 4.7 */ protected ObjectInputStream createObjectInputStream(Socket aSocket) throws IOException { return ProviderPlugin.getDefault().createObjectInputStream(aSocket.getInputStream()); } /** * @param ins object input stream. Will not be <code>null</code> * @return ConnectRequestMessage connect request message read from object input stream * @throws IOException if object cannot be read from stream * @throws ClassNotFoundException if object cannot be read from stream * @since 4.7 */ protected ConnectRequestMessage readConnectRequestMessage(ObjectInputStream ins) throws IOException, ClassNotFoundException { ConnectRequestMessage req = (ConnectRequestMessage) ins.readObject(); if (req == null) throw new InvalidObjectException(INVALID_CONNECT + " Connect request message cannot be null"); //$NON-NLS-1$ return req; } /** * @param aSocket socket * @since 4.7 */ public void handleAccept(Socket aSocket) throws Exception { // Set tcp no delay option aSocket.setTcpNoDelay(true); final ObjectOutputStream oStream = createObjectOutputStream(aSocket); oStream.flush(); final ObjectInputStream iStream = createObjectInputStream(aSocket); final ConnectRequestMessage req = readConnectRequestMessage(iStream); final URI uri = req.getTarget(); if (uri == null) throw new InvalidObjectException(INVALID_CONNECT + " URI connect target cannot be null"); //$NON-NLS-1$ final String path = uri.getPath(); if (path == null) throw new InvalidObjectException(INVALID_CONNECT + " Path cannot be null"); //$NON-NLS-1$ // Given path, lookup associated container final SOContainer srs = get(path); if (srs == null) throw new InvalidObjectException("Container not found for path=" + path); //$NON-NLS-1$ // Create our local messaging interface final Client newClient = new Client(aSocket, iStream, oStream, srs.getMessageReceiver()); // Get output stream lock so nothing is sent until we've responded Object outputStreamLock = newClient.getOutputStreamLock(); // No other threads can access messaging interface until connect request handler has // accepted or rejected connect request synchronized (outputStreamLock) { // Call checkConnect final Serializable resp = ((IConnectRequestHandler) srs).handleConnectRequest(aSocket, path, req.getData(), newClient); // Create connect response wrapper and send it back oStream.writeObject(new ConnectResultMessage(resp)); oStream.flush(); } } }