blob: e9217f9412fc09ebb173c02505c0921d478cb318 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1997-2007 by ProSyst Software GmbH
* http://www.prosyst.com
* 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:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.io.impl;
import java.io.*;
import javax.microedition.io.*;
import org.eclipse.equinox.internal.util.ref.Log;
import org.osgi.framework.*;
import org.osgi.service.io.ConnectionFactory;
import org.osgi.service.io.ConnectorService;
/**
* ConnectorService implementation.
*
* @author Pavlin Dobrev
* @version 1.0
*/
public class ConnectorServiceImpl implements ConnectorService {
static BundleContext bc;
ServiceRegistration reg;
ConnectionFactoryListener listener;
static boolean enableNotification = Activator.getBoolean("eclipse.io.enable.notification");
public static boolean hasDebug;
private static Log log;
public ConnectorServiceImpl(BundleContext bc, Log log) {
ConnectorServiceImpl.log = log;
ConnectorServiceImpl.hasDebug = log.getDebug();
init(bc);
}
public static void debug(int id, String message, Throwable t) {
log.debug(0x1200, id, message, t, false);
}
public ConnectorServiceImpl(BundleContext bc) {
init(bc);
}
private void init(BundleContext bc) {
ConnectorServiceImpl.bc = bc;
if (enableNotification) {
listener = new ConnectionFactoryListener(bc);
}
reg = bc.registerService(ConnectorService.class.getName(), this, null);
}
public void close() {
reg.unregister();
if (listener != null) {
listener.close();
}
}
public Connection open(String uri) throws IOException {
return open(uri, READ_WRITE);
}
public Connection open(String uri, int mode) throws IOException {
return open(uri, mode, false);
}
static char[] chars = {'~', '='};
public Connection open(String uri, int mode, boolean timeouts) throws IOException {
long timeStart = 0;
if (hasDebug) {
debug(16001, uri + ", " + (mode == READ_WRITE ? "READ_WRITE" : (mode == READ) ? "READ" : "WRITE"), null);
timeStart = System.currentTimeMillis();
}
try {
if (uri == null) {
throw new IllegalArgumentException("URL cannot be NULL!");
}
int sPos = uri.indexOf(":");
if (sPos < 1) { // scheme must be at least with 1 symbol
throw new IllegalArgumentException("Does not have scheme");
}
String scheme = uri.substring(0, sPos);
StringBuffer filter = new StringBuffer(scheme.length() + 13);
filter.append('(');
filter.append(ConnectionFactory.IO_SCHEME);
filter.append(chars);
filter.append(scheme);
filter.append(')');
int count = 0;
if (listener != null)
count = ConnectionFactoryListener.count;
Connection c = getConnection(filter.toString(), uri, mode, timeouts, true);
if (c == null && listener != null)
c = ConnectionFactoryListener.getConnectionNotifier(scheme, uri, mode, timeouts, filter.toString(), count);
if (c == null)
throw new ConnectionNotFoundException("Failed to create connection " + uri);
return c;
} finally {
if (hasDebug) {
debug(16002, String.valueOf(System.currentTimeMillis() - timeStart), null);
}
}
}
static protected Connection getConnection(String filter, String uri, int mode, boolean timeouts, boolean connector) throws IOException {
ServiceReference[] cfRefs = null;
Connection ret = null;
try {
cfRefs = bc.getServiceReferences(ConnectionFactory.class.getName(), filter);
} catch (InvalidSyntaxException ex) {
}
if (cfRefs != null) {
sort(cfRefs, 0, cfRefs.length);
}
IOException ioExc = null;
boolean not_found = false;
if (cfRefs != null)
for (int i = 0; i < cfRefs.length; i++) {
ConnectionFactory prov = (ConnectionFactory) bc.getService(cfRefs[i]);
if (prov != null)
try {
not_found = true;
ret = prov.createConnection(uri, mode, timeouts);
} catch (IOException e) {
if (hasDebug) {
debug(16003, prov.getClass().getName(), e);
}
if (ioExc == null)
ioExc = e;
} finally {
if (ret == null)
bc.ungetService(cfRefs[i]);
else {
if (hasDebug) {
debug(16004, prov.getClass().getName(), null);
}
return ret;
}
}
}
if (connector)
try {
ret = Connector.open(uri, mode, timeouts);
} catch (ConnectionNotFoundException ignore) { // returns null ->
// ConnectionNotifier
// is created
debug(16014, null, ignore);
} finally {
if (ret == null) {
if (ioExc != null)
throw ioExc;
if (not_found)
throw new ConnectionNotFoundException("Failed to create connection " + uri);
} else {
if (hasDebug) {
debug(16005, null, null);
}
}
}
return ret;
}
private static void sort(ServiceReference[] array, int start, int end) {
int middle = (start + end) / 2;
if (start + 1 < middle)
sort(array, start, middle);
if (middle + 1 < end)
sort(array, middle, end);
if (start + 1 >= end)
return; // this case can only happen when this method is called by
// the user
if (getRanking(array[middle - 1]) == getRanking(array[middle])) {
if (getServiceID(array[middle - 1]) < getServiceID(array[middle])) {
return;
}
} else if (getRanking(array[middle - 1]) >= getRanking(array[middle])) {
return;
}
if (start + 2 == end) {
ServiceReference temp = array[start];
array[start] = array[middle];
array[middle] = temp;
return;
}
int i1 = start, i2 = middle, i3 = 0;
Object[] merge = new Object[end - start];
while (i1 < middle && i2 < end) {
if (getRanking(array[i1]) == getRanking(array[i2])) {
merge[i3++] = getServiceID(array[i1]) < getServiceID(array[i2]) ? array[i1++] : array[i2++];
} else {
merge[i3++] = getRanking(array[i1]) >= getRanking(array[i2]) ? array[i1++] : array[i2++];
}
}
if (i1 < middle)
System.arraycopy(array, i1, merge, i3, middle - i1);
System.arraycopy(merge, 0, array, start, i2 - start);
}
private static int getRanking(ServiceReference ref) {
Object rank = ref.getProperty(Constants.SERVICE_RANKING);
if (rank == null || !(rank instanceof Integer)) {
return 0;
}
return ((Integer) rank).intValue();
}
private static long getServiceID(ServiceReference ref) {
Object sid = ref.getProperty(Constants.SERVICE_ID);
if (sid == null || !(sid instanceof Long)) {
return 0;
}
return ((Long) sid).intValue();
}
/**
* Create and open an <tt>DataInputStream</tt> object for the specified
* name.
*
* @param name
* the URI for the connection.
* @throws IOException
* if and I/O error occurs
* @throws ConnectionNotFoundException
* if the <tt>Connection</tt> object can not be made or if no
* handler for the requested scheme can be found.
* @throws IllegalArgumentException
* if the given uri is invalid
* @return A <tt>DataInputStream</tt> to the given URI
*/
public DataInputStream openDataInputStream(String name) throws IOException {
long timeBegin = 0;
if (hasDebug) {
debug(16006, name, null);
timeBegin = System.currentTimeMillis();
}
try {
Connection conn = open(name, READ);
if (!(conn instanceof InputConnection)) {
try {
conn.close();
} catch (IOException e) {
}
throw new IOException("Connection does not implement InputConnection:" + conn.getClass());
}
return ((InputConnection) conn).openDataInputStream();
} finally {
if (hasDebug) {
debug(16007, String.valueOf(System.currentTimeMillis() - timeBegin), null);
}
}
}
/**
* Create and open an <tt>DataOutputStream</tt> object for the specified
* name.
*
* @param name
* the URI for the connection.
* @throws IOException
* if and I/O error occurs
* @throws ConnectionNotFoundException
* if the <tt>Connection</tt> object can not be made or if no
* handler for the requested scheme can be found.
* @throws IllegalArgumentException
* if the given uri is invalid
* @return A <tt>DataOutputStream</tt> to the given URI
*/
public DataOutputStream openDataOutputStream(String name) throws IOException {
long timeBegin = 0;
if (hasDebug) {
debug(16008, name, null);
}
try {
Connection conn = open(name, WRITE);
if (!(conn instanceof OutputConnection)) {
try {
conn.close();
} catch (IOException e) {
}
throw new IOException("Connection does not implement OutputConnection:" + conn.getClass());
}
return ((OutputConnection) conn).openDataOutputStream();
} finally {
if (hasDebug) {
debug(16009, String.valueOf(System.currentTimeMillis() - timeBegin), null);
}
}
}
/**
* Create and open an <tt>InputStream</tt> object for the specified name.
*
*
* @param name
* the URI for the connection.
* @throws IOException
* if and I/O error occurs
* @throws ConnectionNotFoundException
* if the <tt>Connection</tt> object can not be made or if no
* handler for the requested scheme can be found.
* @throws IllegalArgumentException
* if the given uri is invalid
* @return A <tt>InputStream</tt> to the given URI
*/
public InputStream openInputStream(String name) throws IOException {
long timeBegin = 0;
if (hasDebug) {
debug(16010, name, null);
timeBegin = System.currentTimeMillis();
}
try {
Connection conn = open(name, READ);
if (!(conn instanceof InputConnection)) {
try {
conn.close();
} catch (IOException e) {
}
throw new IOException("Connection does not implement InputConnection:" + conn.getClass());
}
return ((InputConnection) conn).openInputStream();
} finally {
if (hasDebug) {
debug(16011, String.valueOf(System.currentTimeMillis() - timeBegin), null);
}
}
}
/**
* Create and open an <tt>OutputStream</tt> object for the specified name.
*
* @param name
* the URI for the connection.
* @throws IOException
* if and I/O error occurs
* @throws ConnectionNotFoundException
* if the <tt>Connection</tt> object can not be made or if no
* handler for the requested scheme can be found.
* @throws IllegalArgumentException
* if the given uri is invalid
* @return A <tt>OutputStream</tt> to the given URI
*/
public OutputStream openOutputStream(String name) throws IOException {
long timeBegin = 0;
if (hasDebug) {
debug(16012, name, null);
timeBegin = System.currentTimeMillis();
}
try {
Connection conn = open(name, WRITE);
if (!(conn instanceof OutputConnection)) {
try {
conn.close();
} catch (IOException e) {
}
throw new IOException("Connection does not implement OutputConnection:" + conn.getClass());
}
return ((OutputConnection) conn).openOutputStream();
} finally {
if (hasDebug) {
debug(16013, String.valueOf(System.currentTimeMillis() - timeBegin), null);
}
}
}
}