Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
3f35234cf5
154 changed files with 17348 additions and 315 deletions
|
@ -154,7 +154,7 @@
|
|||
return;
|
||||
} else if (initOptions) {
|
||||
if (initOptions.token || initOptions.refreshToken) {
|
||||
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken, false);
|
||||
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
|
||||
kc.timeSkew = initOptions.timeSkew || 0;
|
||||
|
||||
if (loginIframe.enable) {
|
||||
|
@ -406,10 +406,10 @@
|
|||
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
||||
|
||||
var tokenResponse = JSON.parse(req.responseText);
|
||||
setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], true);
|
||||
|
||||
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
||||
|
||||
setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
|
||||
|
||||
kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
|
||||
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
||||
p.setSuccess(true);
|
||||
|
@ -444,7 +444,7 @@
|
|||
|
||||
kc.clearToken = function() {
|
||||
if (kc.token) {
|
||||
setToken(null, null, null, true);
|
||||
setToken(null, null, null);
|
||||
kc.onAuthLogout && kc.onAuthLogout();
|
||||
if (kc.loginRequired) {
|
||||
kc.login();
|
||||
|
@ -525,7 +525,7 @@
|
|||
function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
|
||||
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
||||
|
||||
setToken(accessToken, refreshToken, idToken, true);
|
||||
setToken(accessToken, refreshToken, idToken);
|
||||
|
||||
if ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
|
||||
(kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
|
||||
|
@ -609,7 +609,7 @@
|
|||
return promise.promise;
|
||||
}
|
||||
|
||||
function setToken(token, refreshToken, idToken, useTokenTime) {
|
||||
function setToken(token, refreshToken, idToken) {
|
||||
if (kc.tokenTimeoutHandle) {
|
||||
clearTimeout(kc.tokenTimeoutHandle);
|
||||
kc.tokenTimeoutHandle = null;
|
||||
|
@ -629,9 +629,12 @@
|
|||
kc.resourceAccess = kc.tokenParsed.resource_access;
|
||||
|
||||
if (kc.onTokenExpired) {
|
||||
var start = useTokenTime ? kc.tokenParsed.iat : (new Date().getTime() / 1000);
|
||||
var expiresIn = kc.tokenParsed.exp - start;
|
||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn * 1000);
|
||||
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
||||
if (expiresIn <= 0) {
|
||||
kc.onTokenExpired();
|
||||
} else {
|
||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
7
dependencies/server-all/pom.xml
vendored
7
dependencies/server-all/pom.xml
vendored
|
@ -83,7 +83,6 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-kerberos-federation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- saml -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
@ -110,6 +109,12 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependencies for RHEL IdM -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-sssd-federation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Built-in Authorization Policy Providers -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Setup for SSSD
|
||||
SSSD_FILE="/etc/sssd/sssd.conf"
|
||||
|
||||
if [ -f "$SSSD_FILE" ];
|
||||
then
|
||||
sed -i '/ldap_tls_cacert/a ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber' $SSSD_FILE
|
||||
sed -i 's/nss, sudo, pam/nss, sudo, pam, ifp/' $SSSD_FILE
|
||||
sed -i '/\[ifp\]/a allowed_uids = root\nuser_attributes = +mail, +telephoneNumber, +givenname, +sn' $SSSD_FILE
|
||||
systemctl restart sssd
|
||||
else
|
||||
echo "Please make sure you have $SSSD_FILE into your system! Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Setup for PAM
|
||||
PAM_FILE="/etc/pam.d/keycloak"
|
||||
|
||||
if [ ! -f "$PAM_FILE" ];
|
||||
then
|
||||
cat <<EOF > $PAM_FILE
|
||||
auth required pam_sss.so
|
||||
account required pam_sss.so
|
||||
EOF
|
||||
else
|
||||
echo "$PAM_FILE already exists. Skipping it..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
<module name="org.keycloak.keycloak-js-adapter" services="import"/>
|
||||
<module name="org.keycloak.keycloak-kerberos-federation" services="import"/>
|
||||
<module name="org.keycloak.keycloak-ldap-federation" services="import"/>
|
||||
<module name="org.keycloak.keycloak-sssd-federation" services="import"/>
|
||||
<module name="org.keycloak.keycloak-server-spi" services="import"/>
|
||||
<module name="org.keycloak.keycloak-model-jpa" services="import"/>
|
||||
<module name="org.keycloak.keycloak-model-mongo" services="import"/>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-sssd-federation">
|
||||
<properties>
|
||||
<property name="jboss.api" value="private"/>
|
||||
</properties>
|
||||
|
||||
<resources>
|
||||
<artifact name="${org.keycloak:keycloak-sssd-federation}"/>
|
||||
</resources>
|
||||
|
||||
<dependencies>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.keycloak.keycloak-core" />
|
||||
<module name="org.keycloak.keycloak-server-spi" />
|
||||
</dependencies>
|
||||
</module>
|
|
@ -35,6 +35,7 @@
|
|||
<modules>
|
||||
<module>ldap</module>
|
||||
<module>kerberos</module>
|
||||
<module>sssd</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
56
federation/sssd/pom.xml
Normal file
56
federation/sssd/pom.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-sssd-federation</artifactId>
|
||||
<name>Keycloak SSSD Federation</name>
|
||||
<description/>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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 cx.ath.matthew;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
public class LibraryLoader {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(LibraryLoader.class.getSimpleName());
|
||||
|
||||
private static final String[] PATHS = {"/usr/lib/", "/usr/lib64/", "/usr/local/lib/", "/opt/local/lib/"};
|
||||
private static final String LIBRARY_NAME = "libunix_dbus_java";
|
||||
private static final String VERSION = "0.0.8";
|
||||
private static boolean loadSucceeded;
|
||||
|
||||
public static void load() {
|
||||
for (String path : PATHS) {
|
||||
try {
|
||||
System.load(String.format("%s/%s.so.%s", path, LIBRARY_NAME, VERSION));
|
||||
loadSucceeded = true;
|
||||
break;
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
loadSucceeded = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!loadSucceeded) LOGGER.log(Level.WARNING, "libunix_dbus_java not found\n" +
|
||||
"Please, make sure you have the package libunix-dbus-java installed.");
|
||||
}
|
||||
}
|
671
federation/sssd/src/main/java/cx/ath/matthew/debug/Debug.java
Normal file
671
federation/sssd/src/main/java/cx/ath/matthew/debug/Debug.java
Normal file
|
@ -0,0 +1,671 @@
|
|||
/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
/* This header is separate from features.h so that the compiler can
|
||||
include it implicitly at the start of every compilation. It must
|
||||
not itself include <features.h> or any other header that includes
|
||||
<features.h> because the implicit include comes before any feature
|
||||
test macros that may be defined in a source file before it first
|
||||
explicitly includes a system header. GCC knows the name of this
|
||||
header in order to preinclude it. */
|
||||
/* glibc's intent is to support the IEC 559 math functionality, real
|
||||
and complex. If the GCC (4.9 and later) predefined macros
|
||||
specifying compiler intent are available, use them to determine
|
||||
whether the overall intent is to support these features; otherwise,
|
||||
presume an older compiler has intent to support these features and
|
||||
define these macros by default. */
|
||||
/* wchar_t uses Unicode 7.0.0. Version 7.0 of the Unicode Standard is
|
||||
synchronized with ISO/IEC 10646:2012, plus Amendments 1 (published
|
||||
on April, 2013) and 2 (not yet published as of February, 2015).
|
||||
Additionally, it includes the accelerated publication of U+20BD
|
||||
RUBLE SIGN. Therefore Unicode 7.0.0 is between 10646:2012 and
|
||||
10646:2014, and so we use the date ISO/IEC 10646:2012 Amd.1 was
|
||||
published. */
|
||||
/* We do not support C11 <threads.h>. */
|
||||
/*
|
||||
* Java Debug Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2005
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.debug;
|
||||
|
||||
import cx.ath.matthew.utils.Hexdump;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Add debugging to your program, has support for large projects with multiple
|
||||
* classes and debug levels per class. Supports optional enabling of debug
|
||||
* per-level per-class and debug targets of files, Streams or stderr.
|
||||
* Also supports timing between debug outputs, printing of stack traces for Throwables
|
||||
* and files/line numbers on each message.
|
||||
* <p>
|
||||
* Debug now automatically figures out which class it was called from, so all
|
||||
* methods passing in the calling class are deprecated.
|
||||
* </p>
|
||||
* <p>
|
||||
* The defaults are to print all messages to stderr with class and method name.
|
||||
* </p>
|
||||
* <p>
|
||||
* Should be called like this:
|
||||
* </p>
|
||||
* <pre>
|
||||
* if (Debug.debug) Debug.print(Debug.INFO, "Debug Message");
|
||||
* </pre>
|
||||
*/
|
||||
public class Debug {
|
||||
/**
|
||||
* This interface can be used to provide custom printing filters
|
||||
* for certain classes.
|
||||
*/
|
||||
public static interface FilterCommand {
|
||||
/**
|
||||
* Called to print debug messages with a custom filter.
|
||||
*
|
||||
* @param output The PrintStream to output to.
|
||||
* @param level The debug level of this message.
|
||||
* @param location The textual location of the message.
|
||||
* @param extra Extra information such as timing details.
|
||||
* @param message The debug message.
|
||||
* @param lines Other lines of a multiple-line debug message.
|
||||
*/
|
||||
public void filter(PrintStream output, int level, String location, String extra, String message, String[] lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highest priority messages
|
||||
*/
|
||||
public static final int CRIT = 1;
|
||||
/**
|
||||
* Error messages
|
||||
*/
|
||||
public static final int ERR = 2;
|
||||
/**
|
||||
* Warnings
|
||||
*/
|
||||
public static final int WARN = 3;
|
||||
/**
|
||||
* Information
|
||||
*/
|
||||
public static final int INFO = 4;
|
||||
/**
|
||||
* Debug messages
|
||||
*/
|
||||
public static final int DEBUG = 5;
|
||||
/**
|
||||
* Verbose debug messages
|
||||
*/
|
||||
public static final int VERBOSE = 6;
|
||||
/**
|
||||
* Set this to false to disable compilation of Debug statements
|
||||
*/
|
||||
public static final boolean debug = false;
|
||||
/**
|
||||
* The current output stream (defaults to System.err)
|
||||
*/
|
||||
public static PrintStream debugout = System.err;
|
||||
private static Properties prop = null;
|
||||
private static boolean timing = false;
|
||||
private static boolean ttrace = false;
|
||||
private static boolean lines = false;
|
||||
private static boolean hexdump = false;
|
||||
private static long last = 0;
|
||||
private static int balen = 36;
|
||||
private static int bawidth = 80;
|
||||
private static Class saveclass = null;
|
||||
//TODO: 1.5 private static Map<Class<? extends Object>, FilterCommand> filterMap = new HashMap<Class<? extends Object>, FilterCommand>();
|
||||
private static Map filterMap = new HashMap();
|
||||
|
||||
/**
|
||||
* Set properties to configure debugging.
|
||||
* Format of properties is class => level, e.g.
|
||||
* <pre>
|
||||
* cx.ath.matthew.io.TeeOutputStream = INFO
|
||||
* cx.ath.matthew.io.DOMPrinter = DEBUG
|
||||
* </pre>
|
||||
* The debug level can be one of CRIT, ERR, WARN, INFO, DEBUG or VERBOSE which
|
||||
* correspond to all messages up to that level. The special words YES, ALL and TRUE
|
||||
* cause all messages to be printed regardless of level. All other terms disable
|
||||
* messages for that class. CRIT and ERR messages are always printed if debugging is enabled
|
||||
* unless explicitly disabled.
|
||||
* The special class name ALL can be used to set the default level for all classes.
|
||||
*
|
||||
* @param prop Properties object to use.
|
||||
*/
|
||||
public static void setProperties(Properties prop) {
|
||||
Debug.prop = prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read which class to debug on at which level from the given File.
|
||||
* Syntax the same as Java Properties files:
|
||||
* <pre>
|
||||
* <class> = <debuglevel>
|
||||
* </pre>
|
||||
* E.G.
|
||||
* <pre>
|
||||
* cx.ath.matthew.io.TeeOutputStream = INFO
|
||||
* cx.ath.matthew.io.DOMPrinter = DEBUG
|
||||
* </pre>
|
||||
* The debug level can be one of CRIT, ERR, WARN, INFO, DEBUG or VERBOSE which
|
||||
* correspond to all messages up to that level. The special words YES, ALL and TRUE
|
||||
* cause all messages to be printed regardless of level. All other terms disable
|
||||
* messages for that class. CRIT and ERR messages are always printed if debugging is enabled
|
||||
* unless explicitly disabled.
|
||||
* The special class name ALL can be used to set the default level for all classes.
|
||||
*
|
||||
* @param f File to read from.
|
||||
*/
|
||||
public static void loadConfig(File f) throws IOException {
|
||||
prop = new Properties();
|
||||
prop.load(new FileInputStream(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static boolean debugging(Class c, int loglevel) {
|
||||
if (debug) {
|
||||
if (null == c) return true;
|
||||
return debugging(c.getName(), loglevel);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean debugging(String s, int loglevel) {
|
||||
if (debug) {
|
||||
try {
|
||||
if (null == s) return true;
|
||||
if (null == prop) return loglevel <= DEBUG;
|
||||
String d = prop.getProperty(s);
|
||||
if (null == d || "".equals(d)) d = prop.getProperty("ALL");
|
||||
if (null == d) return loglevel <= ERR;
|
||||
if ("".equals(d)) return loglevel <= ERR;
|
||||
d = d.toLowerCase();
|
||||
if ("true".equals(d)) return true;
|
||||
if ("yes".equals(d)) return true;
|
||||
if ("all".equals(d)) return true;
|
||||
if ("verbose".equals(d)) return loglevel <= VERBOSE;
|
||||
if ("debug".equals(d)) return loglevel <= DEBUG;
|
||||
if ("info".equals(d)) return loglevel <= INFO;
|
||||
if ("warn".equals(d)) return loglevel <= WARN;
|
||||
if ("err".equals(d)) return loglevel <= ERR;
|
||||
if ("crit".equals(d)) return loglevel <= CRIT;
|
||||
int i = Integer.parseInt(d);
|
||||
return i >= loglevel;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output to the given Stream
|
||||
*/
|
||||
public static void setOutput(PrintStream p) throws IOException {
|
||||
debugout = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output to the given file
|
||||
*/
|
||||
public static void setOutput(String filename) throws IOException {
|
||||
debugout = new PrintStream(new FileOutputStream(filename, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output to the default debug.log
|
||||
*/
|
||||
public static void setOutput() throws IOException {
|
||||
setOutput("./debug.log");
|
||||
}
|
||||
|
||||
/**
|
||||
* Log at DEBUG
|
||||
*
|
||||
* @param d The object to log
|
||||
*/
|
||||
public static void print(Object d) {
|
||||
if (debug) {
|
||||
if (d instanceof String)
|
||||
print(DEBUG, (String) d);
|
||||
else if (d instanceof Throwable)
|
||||
print(DEBUG, (Throwable) d);
|
||||
else if (d instanceof byte[])
|
||||
print(DEBUG, (byte[]) d);
|
||||
else if (d instanceof Map)
|
||||
printMap(DEBUG, (Map) d);
|
||||
else print(DEBUG, d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log at DEBUG
|
||||
*
|
||||
* @param o The object doing the logging
|
||||
* @param d The object to log
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Object o, Object d) {
|
||||
if (debug) {
|
||||
if (o instanceof Class)
|
||||
saveclass = (Class) o;
|
||||
else
|
||||
saveclass = o.getClass();
|
||||
print(d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an Object
|
||||
*
|
||||
* @param o The object doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param d The object to log with d.toString()
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Object o, int loglevel, Object d) {
|
||||
if (debug) {
|
||||
if (o instanceof Class)
|
||||
saveclass = (Class) o;
|
||||
else
|
||||
saveclass = o.getClass();
|
||||
print(loglevel, d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a String
|
||||
*
|
||||
* @param o The object doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param s The log message
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Object o, int loglevel, String s) {
|
||||
if (debug) {
|
||||
if (o instanceof Class)
|
||||
saveclass = (Class) o;
|
||||
else
|
||||
saveclass = o.getClass();
|
||||
print(loglevel, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Throwable
|
||||
*
|
||||
* @param o The object doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param t The throwable to log with .toString and .printStackTrace
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Object o, int loglevel, Throwable t) {
|
||||
if (debug) {
|
||||
if (o instanceof Class)
|
||||
saveclass = (Class) o;
|
||||
else
|
||||
saveclass = o.getClass();
|
||||
print(loglevel, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Throwable
|
||||
*
|
||||
* @param c The class doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param t The throwable to log with .toString and .printStackTrace
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Class c, int loglevel, Throwable t) {
|
||||
if (debug) {
|
||||
saveclass = c;
|
||||
print(loglevel, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Throwable
|
||||
*
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param t The throwable to log with .toString and .printStackTrace
|
||||
* @see #setThrowableTraces to turn on stack traces.
|
||||
*/
|
||||
public static void print(int loglevel, Throwable t) {
|
||||
if (debug) {
|
||||
String timestr = "";
|
||||
String[] data = getTraceElements();
|
||||
if (debugging(data[0], loglevel)) {
|
||||
if (timing) {
|
||||
long now = System.currentTimeMillis();
|
||||
timestr = "{" + (now - last) + "} ";
|
||||
last = now;
|
||||
}
|
||||
String[] lines = null;
|
||||
if (ttrace) {
|
||||
StackTraceElement[] ste = t.getStackTrace();
|
||||
lines = new String[ste.length];
|
||||
for (int i = 0; i < ste.length; i++)
|
||||
lines[i] = "\tat " + ste[i].toString();
|
||||
}
|
||||
_print(t.getClass(), loglevel, data[0] + "." + data[1] + "()" + data[2], timestr, t.toString(), lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a byte array
|
||||
*
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param b The byte array to print.
|
||||
* @see #setHexDump to enable hex dumping.
|
||||
* @see #setByteArrayCount to change how many bytes are printed.
|
||||
* @see #setByteArrayWidth to change the formatting width of hex.
|
||||
*/
|
||||
public static void print(int loglevel, byte[] b) {
|
||||
if (debug) {
|
||||
String timestr = "";
|
||||
String[] data = getTraceElements();
|
||||
if (debugging(data[0], loglevel)) {
|
||||
if (timing) {
|
||||
long now = System.currentTimeMillis();
|
||||
timestr = "{" + (now - last) + "} ";
|
||||
last = now;
|
||||
}
|
||||
String[] lines = null;
|
||||
if (hexdump) {
|
||||
if (balen >= b.length)
|
||||
lines = Hexdump.format(b, bawidth).split("\n");
|
||||
else {
|
||||
byte[] buf = new byte[balen];
|
||||
System.arraycopy(b, 0, buf, 0, balen);
|
||||
lines = Hexdump.format(buf, bawidth).split("\n");
|
||||
}
|
||||
}
|
||||
_print(b.getClass(), loglevel, data[0] + "." + data[1] + "()" + data[2], timestr, b.length + " bytes", lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a String
|
||||
*
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param s The string to log with d.toString()
|
||||
*/
|
||||
public static void print(int loglevel, String s) {
|
||||
if (debug)
|
||||
print(loglevel, (Object) s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an Object
|
||||
*
|
||||
* @param c The class doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param d The object to log with d.toString()
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Class c, int loglevel, Object d) {
|
||||
if (debug) {
|
||||
saveclass = c;
|
||||
print(loglevel, d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a String
|
||||
*
|
||||
* @param c The class doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param s The log message
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void print(Class c, int loglevel, String s) {
|
||||
if (debug) {
|
||||
saveclass = c;
|
||||
print(loglevel, s);
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] getTraceElements() {
|
||||
String[] data = new String[]{"", "", ""};
|
||||
try {
|
||||
Method m = Thread.class.getMethod("getStackTrace", new Class[0]);
|
||||
StackTraceElement[] stes = (StackTraceElement[]) m.invoke(Thread.currentThread(), new Object[0]);
|
||||
for (StackTraceElement ste : stes) {
|
||||
if (Debug.class.getName().equals(ste.getClassName())) continue;
|
||||
if (Thread.class.getName().equals(ste.getClassName())) continue;
|
||||
if (Method.class.getName().equals(ste.getClassName())) continue;
|
||||
if (ste.getClassName().startsWith("sun.reflect")) continue;
|
||||
data[0] = ste.getClassName();
|
||||
data[1] = ste.getMethodName();
|
||||
if (lines)
|
||||
data[2] = " " + ste.getFileName() + ":" + ste.getLineNumber();
|
||||
break;
|
||||
}
|
||||
} catch (NoSuchMethodException NSMe) {
|
||||
if (null != saveclass)
|
||||
data[0] = saveclass.getName();
|
||||
} catch (IllegalAccessException IAe) {
|
||||
} catch (InvocationTargetException ITe) {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an Object
|
||||
*
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param o The object to log
|
||||
*/
|
||||
public static void print(int loglevel, Object o) {
|
||||
if (debug) {
|
||||
String timestr = "";
|
||||
String[] data = getTraceElements();
|
||||
if (debugging(data[0], loglevel)) {
|
||||
if (timing) {
|
||||
long now = System.currentTimeMillis();
|
||||
timestr = "{" + (now - last) + "} ";
|
||||
last = now;
|
||||
}
|
||||
_print(o.getClass(), loglevel, data[0] + "." + data[1] + "()" + data[2], timestr, o.toString(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Map
|
||||
*
|
||||
* @param o The object doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param m The Map to print out
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void printMap(Object o, int loglevel, Map m) {
|
||||
if (debug) {
|
||||
if (o instanceof Class)
|
||||
saveclass = (Class) o;
|
||||
else
|
||||
saveclass = o.getClass();
|
||||
printMap(loglevel, m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Map
|
||||
*
|
||||
* @param c The class doing the logging
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param m The Map to print out
|
||||
* @deprecated In Java 1.5 calling class is automatically identified, no need to pass it in.
|
||||
*/
|
||||
//TODO: 1.5 @Deprecated()
|
||||
public static void printMap(Class c, int loglevel, Map m) {
|
||||
if (debug) {
|
||||
saveclass = c;
|
||||
printMap(loglevel, m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Map at DEBUG log level
|
||||
*
|
||||
* @param m The Map to print out
|
||||
*/
|
||||
public static void printMap(Map m) {
|
||||
printMap(DEBUG, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Map
|
||||
*
|
||||
* @param loglevel The level to log at (DEBUG, WARN, etc)
|
||||
* @param m The Map to print out
|
||||
*/
|
||||
public static void printMap(int loglevel, Map m) {
|
||||
if (debug) {
|
||||
String timestr = "";
|
||||
String[] data = getTraceElements();
|
||||
if (debugging(data[0], loglevel)) {
|
||||
if (timing) {
|
||||
long now = System.currentTimeMillis();
|
||||
timestr = "{" + (now - last) + "} ";
|
||||
last = now;
|
||||
}
|
||||
Iterator i = m.keySet().iterator();
|
||||
String[] lines = new String[m.size()];
|
||||
int j = 0;
|
||||
while (i.hasNext()) {
|
||||
Object key = i.next();
|
||||
lines[j++] = "\t\t- " + key + " => " + m.get(key);
|
||||
}
|
||||
_print(m.getClass(), loglevel, data[0] + "." + data[1] + "()" + data[2], timestr, "Map:", lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable stack traces in Debuging throwables.
|
||||
*/
|
||||
public static void setThrowableTraces(boolean ttrace) {
|
||||
Debug.ttrace = ttrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable timing in Debug messages.
|
||||
*/
|
||||
public static void setTiming(boolean timing) {
|
||||
Debug.timing = timing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable line numbers.
|
||||
*/
|
||||
public static void setLineNos(boolean lines) {
|
||||
Debug.lines = lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable hexdumps.
|
||||
*/
|
||||
public static void setHexDump(boolean hexdump) {
|
||||
Debug.hexdump = hexdump;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of hexdumps.
|
||||
* (Default: 36)
|
||||
*/
|
||||
public static void setByteArrayCount(int count) {
|
||||
Debug.balen = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the formatted width of hexdumps.
|
||||
* (Default: 80 chars)
|
||||
*/
|
||||
public static void setByteArrayWidth(int width) {
|
||||
Debug.bawidth = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter command for a specific type.
|
||||
* This command will be called with the output stream
|
||||
* and the text to be sent. It should perform any
|
||||
* changes necessary to the text and then print the
|
||||
* result to the output stream.
|
||||
*/
|
||||
public static void addFilterCommand(Class c, FilterCommand f)
|
||||
//TODO 1.5: public static void addFilterCommand(Class<? extends Object> c, FilterCommand f)
|
||||
{
|
||||
filterMap.put(c, f);
|
||||
}
|
||||
|
||||
private static void _print(Class c, int level, String loc, String extra, String message, String[] lines) {
|
||||
//TODO 1.5: FilterCommand f = filterMap.get(c);
|
||||
FilterCommand f = (FilterCommand) filterMap.get(c);
|
||||
if (null == f) {
|
||||
debugout.println("[" + loc + "] " + extra + message);
|
||||
if (null != lines)
|
||||
for (String s : lines)
|
||||
debugout.println(s);
|
||||
} else
|
||||
f.filter(debugout, level, loc, extra, message, lines);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
import java.net.SocketException;
|
||||
|
||||
public class NotConnectedException extends SocketException {
|
||||
public NotConnectedException() {
|
||||
super("The Socket is Not Connected");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class USInputStream extends InputStream {
|
||||
public static final int MSG_DONTWAIT = 0x40;
|
||||
|
||||
private native int native_recv(int sock, byte[] b, int off, int len, int flags, int timeout) throws IOException;
|
||||
|
||||
private int sock;
|
||||
boolean closed = false;
|
||||
private byte[] onebuf = new byte[1];
|
||||
private UnixSocket us;
|
||||
private boolean blocking = true;
|
||||
private int flags = 0;
|
||||
private int timeout = 0;
|
||||
|
||||
public USInputStream(int sock, UnixSocket us) {
|
||||
this.sock = sock;
|
||||
this.us = us;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
closed = true;
|
||||
us.close();
|
||||
}
|
||||
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
int rv = 0;
|
||||
while (0 >= rv) rv = read(onebuf);
|
||||
if (-1 == rv) return -1;
|
||||
return 0 > onebuf[0] ? -onebuf[0] : onebuf[0];
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (closed) throw new NotConnectedException();
|
||||
int count = native_recv(sock, b, off, len, flags, timeout);
|
||||
/* Yes, I really want to do this. Recv returns 0 for 'connection shut down'.
|
||||
* read() returns -1 for 'end of stream.
|
||||
* Recv returns -1 for 'EAGAIN' (all other errors cause an exception to be raised)
|
||||
* whereas read() returns 0 for '0 bytes read', so yes, I really want to swap them here.
|
||||
*/
|
||||
if (0 == count) return -1;
|
||||
else if (-1 == count) return 0;
|
||||
else return count;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
public UnixSocket getSocket() {
|
||||
return us;
|
||||
}
|
||||
|
||||
public void setBlocking(boolean enable) {
|
||||
flags = enable ? 0 : MSG_DONTWAIT;
|
||||
}
|
||||
|
||||
public void setSoTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class USOutputStream extends OutputStream {
|
||||
private native int native_send(int sock, byte[] b, int off, int len) throws IOException;
|
||||
|
||||
private native int native_send(int sock, byte[][] b) throws IOException;
|
||||
|
||||
private int sock;
|
||||
boolean closed = false;
|
||||
private byte[] onebuf = new byte[1];
|
||||
private UnixSocket us;
|
||||
|
||||
public USOutputStream(int sock, UnixSocket us) {
|
||||
this.sock = sock;
|
||||
this.us = us;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
closed = true;
|
||||
us.close();
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
} // no-op, we do not buffer
|
||||
|
||||
public void write(byte[][] b) throws IOException {
|
||||
if (closed) throw new NotConnectedException();
|
||||
native_send(sock, b);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (closed) throw new NotConnectedException();
|
||||
native_send(sock, b, off, len);
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
onebuf[0] = (byte) (b % 0x7F);
|
||||
if (1 == (b % 0x80)) onebuf[0] = (byte) -onebuf[0];
|
||||
write(onebuf);
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
public UnixSocket getSocket() {
|
||||
return us;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An IO Exception which occurred during UNIX Socket IO
|
||||
*/
|
||||
public class UnixIOException extends IOException {
|
||||
private int no;
|
||||
private String message;
|
||||
|
||||
public UnixIOException(int no, String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.no = no;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
import cx.ath.matthew.LibraryLoader;
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Represents a UnixSocket.
|
||||
*/
|
||||
public class UnixSocket {
|
||||
static {
|
||||
LibraryLoader.load();
|
||||
}
|
||||
|
||||
private native void native_set_pass_cred(int sock, boolean passcred) throws IOException;
|
||||
|
||||
private native int native_connect(String address, boolean abs) throws IOException;
|
||||
|
||||
private native void native_close(int sock) throws IOException;
|
||||
|
||||
private native int native_getPID(int sock);
|
||||
|
||||
private native int native_getUID(int sock);
|
||||
|
||||
private native int native_getGID(int sock);
|
||||
|
||||
private native void native_send_creds(int sock, byte data) throws IOException;
|
||||
|
||||
private native byte native_recv_creds(int sock, int[] creds) throws IOException;
|
||||
|
||||
private UnixSocketAddress address = null;
|
||||
private USOutputStream os = null;
|
||||
private USInputStream is = null;
|
||||
private boolean closed = false;
|
||||
private boolean connected = false;
|
||||
private boolean passcred = false;
|
||||
private int sock = 0;
|
||||
private boolean blocking = true;
|
||||
private int uid = -1;
|
||||
private int pid = -1;
|
||||
private int gid = -1;
|
||||
|
||||
UnixSocket(int sock, UnixSocketAddress address) {
|
||||
this.sock = sock;
|
||||
this.address = address;
|
||||
this.connected = true;
|
||||
this.os = new USOutputStream(sock, this);
|
||||
this.is = new USInputStream(sock, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an unconnected socket.
|
||||
*/
|
||||
public UnixSocket() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket connected to the given address.
|
||||
*
|
||||
* @param address The Unix Socket address to connect to
|
||||
*/
|
||||
public UnixSocket(UnixSocketAddress address) throws IOException {
|
||||
connect(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket connected to the given address.
|
||||
*
|
||||
* @param address The Unix Socket address to connect to
|
||||
*/
|
||||
public UnixSocket(String address) throws IOException {
|
||||
this(new UnixSocketAddress(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the socket to this address.
|
||||
*
|
||||
* @param address The Unix Socket address to connect to
|
||||
*/
|
||||
public void connect(UnixSocketAddress address) throws IOException {
|
||||
if (connected) close();
|
||||
this.sock = native_connect(address.path, address.abs);
|
||||
this.os = new USOutputStream(this.sock, this);
|
||||
this.is = new USInputStream(this.sock, this);
|
||||
this.address = address;
|
||||
this.connected = true;
|
||||
this.closed = false;
|
||||
this.is.setBlocking(blocking);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the socket to this address.
|
||||
*
|
||||
* @param address The Unix Socket address to connect to
|
||||
*/
|
||||
public void connect(String address) throws IOException {
|
||||
connect(new UnixSocketAddress(address));
|
||||
}
|
||||
|
||||
public void finalize() {
|
||||
try {
|
||||
close();
|
||||
} catch (IOException IOe) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*/
|
||||
public synchronized void close() throws IOException {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Closing socket");
|
||||
native_close(sock);
|
||||
sock = 0;
|
||||
this.closed = true;
|
||||
this.connected = false;
|
||||
os = null;
|
||||
is = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream for reading from the socket.
|
||||
*
|
||||
* @return An InputStream connected to this socket.
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream for writing to the socket.
|
||||
*
|
||||
* @return An OutputStream connected to this socket.
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
return os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address this socket is connected to.
|
||||
* Returns null if the socket is unconnected.
|
||||
*
|
||||
* @return The UnixSocketAddress the socket is connected to
|
||||
*/
|
||||
public UnixSocketAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a single byte of data with credentials.
|
||||
* (Works on BSDs)
|
||||
*
|
||||
* @param data The byte of data to send.
|
||||
*/
|
||||
public void sendCredentialByte(byte data) throws IOException {
|
||||
if (!connected) throw new NotConnectedException();
|
||||
native_send_creds(sock, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a single byte of data, with credentials.
|
||||
* (Works on BSDs)
|
||||
*
|
||||
* @param data The byte of data to send.
|
||||
* @see getPeerUID
|
||||
* @see getPeerPID
|
||||
* @see getPeerGID
|
||||
*/
|
||||
public byte recvCredentialByte() throws IOException {
|
||||
if (!connected) throw new NotConnectedException();
|
||||
int[] creds = new int[]{-1, -1, -1};
|
||||
byte data = native_recv_creds(sock, creds);
|
||||
pid = creds[0];
|
||||
uid = creds[1];
|
||||
gid = creds[2];
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the credential passing status.
|
||||
* (only effective on linux)
|
||||
*
|
||||
* @return The current status of credential passing.
|
||||
* @see setPassCred
|
||||
*/
|
||||
public boolean getPassCred() {
|
||||
return passcred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the uid of the remote process.
|
||||
* Some data must have been received on the socket to do this.
|
||||
* Either setPassCred must be called on Linux first, or recvCredentialByte
|
||||
* on BSD.
|
||||
*
|
||||
* @return the UID or -1 if it is not available
|
||||
*/
|
||||
public int getPeerUID() {
|
||||
if (-1 == uid)
|
||||
uid = native_getUID(sock);
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the gid of the remote process.
|
||||
* Some data must have been received on the socket to do this.
|
||||
* Either setPassCred must be called on Linux first, or recvCredentialByte
|
||||
* on BSD.
|
||||
*
|
||||
* @return the GID or -1 if it is not available
|
||||
*/
|
||||
public int getPeerGID() {
|
||||
if (-1 == gid)
|
||||
gid = native_getGID(sock);
|
||||
return gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pid of the remote process.
|
||||
* Some data must have been received on the socket to do this.
|
||||
* Either setPassCred must be called on Linux first, or recvCredentialByte
|
||||
* on BSD.
|
||||
*
|
||||
* @return the PID or -1 if it is not available
|
||||
*/
|
||||
public int getPeerPID() {
|
||||
if (-1 == pid)
|
||||
pid = native_getPID(sock);
|
||||
return pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the credential passing status.
|
||||
* (Only does anything on linux, for other OS, you need
|
||||
* to use send/recv credentials)
|
||||
*
|
||||
* @param enable Set to true for credentials to be passed.
|
||||
*/
|
||||
public void setPassCred(boolean enable) throws IOException {
|
||||
native_set_pass_cred(sock, enable);
|
||||
passcred = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the blocking mode.
|
||||
*
|
||||
* @return true if reads are blocking.
|
||||
* @see setBlocking
|
||||
*/
|
||||
public boolean getBlocking() {
|
||||
return blocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the blocking mode.
|
||||
*
|
||||
* @param enable Set to false for non-blocking reads.
|
||||
*/
|
||||
public void setBlocking(boolean enable) {
|
||||
blocking = enable;
|
||||
if (null != is) is.setBlocking(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the socket status.
|
||||
*
|
||||
* @return true if closed.
|
||||
*/
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the socket status.
|
||||
*
|
||||
* @return true if connected.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the socket status.
|
||||
*
|
||||
* @return true if the input stream has been shutdown
|
||||
*/
|
||||
public boolean isInputShutdown() {
|
||||
return is.isClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the socket status.
|
||||
*
|
||||
* @return true if the output stream has been shutdown
|
||||
*/
|
||||
public boolean isOutputShutdown() {
|
||||
return os.isClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the input stream.
|
||||
* Subsequent reads on the associated InputStream will fail.
|
||||
*/
|
||||
public void shutdownInput() {
|
||||
is.closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the output stream.
|
||||
* Subsequent writes to the associated OutputStream will fail.
|
||||
*/
|
||||
public void shutdownOutput() {
|
||||
os.closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timeout of read requests.
|
||||
*/
|
||||
public void setSoTimeout(int timeout) {
|
||||
is.setSoTimeout(timeout);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Java Unix Sockets Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2004
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package cx.ath.matthew.unix;
|
||||
|
||||
/**
|
||||
* Represents an address for a Unix Socket
|
||||
*/
|
||||
public class UnixSocketAddress {
|
||||
String path;
|
||||
boolean abs;
|
||||
|
||||
/**
|
||||
* Create the address.
|
||||
*
|
||||
* @param path The path to the Unix Socket.
|
||||
* @param abs True if this should be an abstract socket.
|
||||
*/
|
||||
public UnixSocketAddress(String path, boolean abs) {
|
||||
this.path = path;
|
||||
this.abs = abs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the address.
|
||||
*
|
||||
* @param path The path to the Unix Socket.
|
||||
*/
|
||||
public UnixSocketAddress(String path) {
|
||||
this.path = path;
|
||||
this.abs = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this an address for an abstract socket.
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return abs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Address as a String.
|
||||
*/
|
||||
public String toString() {
|
||||
return "unix" + (abs ? ":abstract" : "") + ":path=" + path;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof UnixSocketAddress)) return false;
|
||||
return ((UnixSocketAddress) o).path.equals(this.path);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return path.hashCode();
|
||||
}
|
||||
}
|
147
federation/sssd/src/main/java/cx/ath/matthew/utils/Hexdump.java
Normal file
147
federation/sssd/src/main/java/cx/ath/matthew/utils/Hexdump.java
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Java Hexdump Library
|
||||
*
|
||||
* Copyright (c) Matthew Johnson 2005
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* To Contact the author, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
|
||||
package cx.ath.matthew.utils;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class Hexdump {
|
||||
public static final char[] hexchars = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
public static String toHex(byte[] buf) {
|
||||
return toHex(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public static String toHex(byte[] buf, int ofs, int len) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int j = ofs + len;
|
||||
for (int i = ofs; i < j; i++) {
|
||||
if (i < buf.length) {
|
||||
sb.append(hexchars[(buf[i] & 0xF0) >> 4]);
|
||||
sb.append(hexchars[buf[i] & 0x0F]);
|
||||
sb.append(' ');
|
||||
} else {
|
||||
sb.append(' ');
|
||||
sb.append(' ');
|
||||
sb.append(' ');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String toAscii(byte[] buf) {
|
||||
return toAscii(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public static String toAscii(byte[] buf, int ofs, int len) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int j = ofs + len;
|
||||
for (int i = ofs; i < j; i++) {
|
||||
if (i < buf.length) {
|
||||
if (20 <= buf[i] && 126 >= buf[i])
|
||||
sb.append((char) buf[i]);
|
||||
else
|
||||
sb.append('.');
|
||||
} else
|
||||
sb.append(' ');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String format(byte[] buf) {
|
||||
return format(buf, 80);
|
||||
}
|
||||
|
||||
public static String format(byte[] buf, int width) {
|
||||
int bs = (width - 8) / 4;
|
||||
int i = 0;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
do {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
sb.append(hexchars[(i << (j * 4) & 0xF00000) >> 20]);
|
||||
}
|
||||
sb.append('\t');
|
||||
sb.append(toHex(buf, i, bs));
|
||||
sb.append(' ');
|
||||
sb.append(toAscii(buf, i, bs));
|
||||
sb.append('\n');
|
||||
i += bs;
|
||||
} while (i < buf.length);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void print(byte[] buf) {
|
||||
print(buf, System.err);
|
||||
}
|
||||
|
||||
public static void print(byte[] buf, int width) {
|
||||
print(buf, width, System.err);
|
||||
}
|
||||
|
||||
public static void print(byte[] buf, int width, PrintStream out) {
|
||||
out.print(format(buf, width));
|
||||
}
|
||||
|
||||
public static void print(byte[] buf, PrintStream out) {
|
||||
out.print(format(buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string which can be written to a Java source file as part
|
||||
* of a static initializer for a byte array.
|
||||
* Returns data in the format 0xAB, 0xCD, ....
|
||||
* use like:
|
||||
* javafile.print("byte[] data = {")
|
||||
* javafile.print(Hexdump.toByteArray(data));
|
||||
* javafile.println("};");
|
||||
*/
|
||||
public static String toByteArray(byte[] buf) {
|
||||
return toByteArray(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string which can be written to a Java source file as part
|
||||
* of a static initializer for a byte array.
|
||||
* Returns data in the format 0xAB, 0xCD, ....
|
||||
* use like:
|
||||
* javafile.print("byte[] data = {")
|
||||
* javafile.print(Hexdump.toByteArray(data));
|
||||
* javafile.println("};");
|
||||
*/
|
||||
public static String toByteArray(byte[] buf, int ofs, int len) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = ofs; i < len && i < buf.length; i++) {
|
||||
sb.append('0');
|
||||
sb.append('x');
|
||||
sb.append(hexchars[(buf[i] & 0xF0) >> 4]);
|
||||
sb.append(hexchars[buf[i] & 0x0F]);
|
||||
if ((i + 1) < len && (i + 1) < buf.length)
|
||||
sb.append(',');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
530
federation/sssd/src/main/java/org/freedesktop/DBus.java
Normal file
530
federation/sssd/src/main/java/org/freedesktop/DBus.java
Normal file
|
@ -0,0 +1,530 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop;
|
||||
|
||||
import org.freedesktop.dbus.DBusInterface;
|
||||
import org.freedesktop.dbus.DBusSignal;
|
||||
import org.freedesktop.dbus.Position;
|
||||
import org.freedesktop.dbus.Struct;
|
||||
import org.freedesktop.dbus.Tuple;
|
||||
import org.freedesktop.dbus.UInt16;
|
||||
import org.freedesktop.dbus.UInt32;
|
||||
import org.freedesktop.dbus.UInt64;
|
||||
import org.freedesktop.dbus.Variant;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface DBus extends DBusInterface {
|
||||
public static final int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01;
|
||||
public static final int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02;
|
||||
public static final int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04;
|
||||
public static final int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1;
|
||||
public static final int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2;
|
||||
public static final int DBUS_REQUEST_NAME_REPLY_EXISTS = 3;
|
||||
public static final int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4;
|
||||
public static final int DBUS_RELEASE_NAME_REPLY_RELEASED = 1;
|
||||
public static final int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2;
|
||||
public static final int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3;
|
||||
public static final int DBUS_START_REPLY_SUCCESS = 1;
|
||||
public static final int DBUS_START_REPLY_ALREADY_RUNNING = 2;
|
||||
|
||||
/**
|
||||
* All DBus Applications should respond to the Ping method on this interface
|
||||
*/
|
||||
public interface Peer extends DBusInterface {
|
||||
public void Ping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Objects can provide introspection data via this interface and method.
|
||||
* See the <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format">Introspection Format</a>.
|
||||
*/
|
||||
public interface Introspectable extends DBusInterface {
|
||||
/**
|
||||
* @return The XML introspection data for this object
|
||||
*/
|
||||
public String Introspect();
|
||||
}
|
||||
|
||||
/**
|
||||
* A standard properties interface.
|
||||
*/
|
||||
public interface Properties extends DBusInterface {
|
||||
/**
|
||||
* Get the value for the given property.
|
||||
*
|
||||
* @param interface_name The interface this property is associated with.
|
||||
* @param property_name The name of the property.
|
||||
* @return The value of the property (may be any valid DBus type).
|
||||
*/
|
||||
public <A> A Get(String interface_name, String property_name);
|
||||
|
||||
/**
|
||||
* Set the value for the given property.
|
||||
*
|
||||
* @param interface_name The interface this property is associated with.
|
||||
* @param property_name The name of the property.
|
||||
* @param value The new value of the property (may be any valid DBus type).
|
||||
*/
|
||||
public <A> void Set(String interface_name, String property_name, A value);
|
||||
|
||||
/**
|
||||
* Get all properties and values.
|
||||
*
|
||||
* @param interface_name The interface the properties is associated with.
|
||||
* @return The properties mapped to their values.
|
||||
*/
|
||||
public Map<String, Variant> GetAll(String interface_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages generated locally in the application.
|
||||
*/
|
||||
public interface Local extends DBusInterface {
|
||||
public class Disconnected extends DBusSignal {
|
||||
public Disconnected(String path) throws DBusException {
|
||||
super(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial message to register ourselves on the Bus.
|
||||
*
|
||||
* @return The unique name of this connection to the Bus.
|
||||
*/
|
||||
public String Hello();
|
||||
|
||||
/**
|
||||
* Lists all connected names on the Bus.
|
||||
*
|
||||
* @return An array of all connected names.
|
||||
*/
|
||||
public String[] ListNames();
|
||||
|
||||
/**
|
||||
* Determine if a name has an owner.
|
||||
*
|
||||
* @param name The name to query.
|
||||
* @return true if the name has an owner.
|
||||
*/
|
||||
public boolean NameHasOwner(String name);
|
||||
|
||||
/**
|
||||
* Get the connection unique name that owns the given name.
|
||||
*
|
||||
* @param name The name to query.
|
||||
* @return The connection which owns the name.
|
||||
*/
|
||||
public String GetNameOwner(String name);
|
||||
|
||||
/**
|
||||
* Get the Unix UID that owns a connection name.
|
||||
*
|
||||
* @param connection_name The connection name.
|
||||
* @return The Unix UID that owns it.
|
||||
*/
|
||||
public UInt32 GetConnectionUnixUser(String connection_name);
|
||||
|
||||
/**
|
||||
* Start a service. If the given service is not provided
|
||||
* by any application, it will be started according to the .service file
|
||||
* for that service.
|
||||
*
|
||||
* @param name The service name to start.
|
||||
* @param flags Unused.
|
||||
* @return DBUS_START_REPLY constants.
|
||||
*/
|
||||
public UInt32 StartServiceByName(String name, UInt32 flags);
|
||||
|
||||
/**
|
||||
* Request a name on the bus.
|
||||
*
|
||||
* @param name The name to request.
|
||||
* @param flags DBUS_NAME flags.
|
||||
* @return DBUS_REQUEST_NAME_REPLY constants.
|
||||
*/
|
||||
public UInt32 RequestName(String name, UInt32 flags);
|
||||
|
||||
/**
|
||||
* Release a name on the bus.
|
||||
*
|
||||
* @param name The name to release.
|
||||
* @return DBUS_RELEASE_NAME_REPLY constants.
|
||||
*/
|
||||
public UInt32 ReleaseName(String name);
|
||||
|
||||
/**
|
||||
* Add a match rule.
|
||||
* Will cause you to receive messages that aren't directed to you which
|
||||
* match this rule.
|
||||
*
|
||||
* @param matchrule The Match rule as a string. Format Undocumented.
|
||||
*/
|
||||
public void AddMatch(String matchrule) throws Error.MatchRuleInvalid;
|
||||
|
||||
/**
|
||||
* Remove a match rule.
|
||||
* Will cause you to stop receiving messages that aren't directed to you which
|
||||
* match this rule.
|
||||
*
|
||||
* @param matchrule The Match rule as a string. Format Undocumented.
|
||||
*/
|
||||
public void RemoveMatch(String matchrule) throws Error.MatchRuleInvalid;
|
||||
|
||||
/**
|
||||
* List the connections currently queued for a name.
|
||||
*
|
||||
* @param name The name to query
|
||||
* @return A list of unique connection IDs.
|
||||
*/
|
||||
public String[] ListQueuedOwners(String name);
|
||||
|
||||
/**
|
||||
* Returns the proccess ID associated with a connection.
|
||||
*
|
||||
* @param connection_name The name of the connection
|
||||
* @return The PID of the connection.
|
||||
*/
|
||||
public UInt32 GetConnectionUnixProcessID(String connection_name);
|
||||
|
||||
/**
|
||||
* Does something undocumented.
|
||||
*/
|
||||
public Byte[] GetConnectionSELinuxSecurityContext(String a);
|
||||
|
||||
/**
|
||||
* Does something undocumented.
|
||||
*/
|
||||
public void ReloadConfig();
|
||||
|
||||
/**
|
||||
* Signal sent when the owner of a name changes
|
||||
*/
|
||||
public class NameOwnerChanged extends DBusSignal {
|
||||
public final String name;
|
||||
public final String old_owner;
|
||||
public final String new_owner;
|
||||
|
||||
public NameOwnerChanged(String path, String name, String old_owner, String new_owner) throws DBusException {
|
||||
super(path, new Object[]{name, old_owner, new_owner});
|
||||
this.name = name;
|
||||
this.old_owner = old_owner;
|
||||
this.new_owner = new_owner;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal sent to a connection when it loses a name
|
||||
*/
|
||||
public class NameLost extends DBusSignal {
|
||||
public final String name;
|
||||
|
||||
public NameLost(String path, String name) throws DBusException {
|
||||
super(path, name);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal sent to a connection when it aquires a name
|
||||
*/
|
||||
public class NameAcquired extends DBusSignal {
|
||||
public final String name;
|
||||
|
||||
public NameAcquired(String path, String name) throws DBusException {
|
||||
super(path, name);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains standard errors that can be thrown from methods.
|
||||
*/
|
||||
public interface Error {
|
||||
/**
|
||||
* Thrown if the method called was unknown on the remote object
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UnknownMethod extends DBusExecutionException {
|
||||
public UnknownMethod(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown if the object was unknown on a remote connection
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UnknownObject extends DBusExecutionException {
|
||||
public UnknownObject(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown if the requested service was not available
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ServiceUnknown extends DBusExecutionException {
|
||||
public ServiceUnknown(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown if the match rule is invalid
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MatchRuleInvalid extends DBusExecutionException {
|
||||
public MatchRuleInvalid(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown if there is no reply to a method call
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NoReply extends DBusExecutionException {
|
||||
public NoReply(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown if a message is denied due to a security policy
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AccessDenied extends DBusExecutionException {
|
||||
public AccessDenied(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the interface or method, returned in the introspection data
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Description {
|
||||
String value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that a DBus interface or method is deprecated
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Deprecated {
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains method-specific annotations
|
||||
*/
|
||||
public interface Method {
|
||||
/**
|
||||
* Methods annotated with this do not send a reply
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NoReply {
|
||||
}
|
||||
|
||||
/**
|
||||
* Give an error that the method can return
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Error {
|
||||
String value();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains GLib-specific annotations
|
||||
*/
|
||||
public interface GLib {
|
||||
/**
|
||||
* Define a C symbol to map to this method. Used by GLib only
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CSymbol {
|
||||
String value();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains Binding-test interfaces
|
||||
*/
|
||||
public interface Binding {
|
||||
public interface SingleTests extends DBusInterface {
|
||||
@Description("Returns the sum of the values in the input list")
|
||||
public UInt32 Sum(byte[] a);
|
||||
}
|
||||
|
||||
public interface TestClient extends DBusInterface {
|
||||
@Description("when the trigger signal is received, this method should be called on the sending process/object.")
|
||||
public void Response(UInt16 a, double b);
|
||||
|
||||
@Description("Causes a callback")
|
||||
public static class Trigger extends DBusSignal {
|
||||
public final UInt16 a;
|
||||
public final double b;
|
||||
|
||||
public Trigger(String path, UInt16 a, double b) throws DBusException {
|
||||
super(path, a, b);
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface Tests extends DBusInterface {
|
||||
@Description("Returns whatever it is passed")
|
||||
public <T> Variant<T> Identity(Variant<T> input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public byte IdentityByte(byte input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public boolean IdentityBool(boolean input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public short IdentityInt16(short input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt16 IdentityUInt16(UInt16 input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public int IdentityInt32(int input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt32 IdentityUInt32(UInt32 input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public long IdentityInt64(long input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt64 IdentityUInt64(UInt64 input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public double IdentityDouble(double input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public String IdentityString(String input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public <T> Variant<T>[] IdentityArray(Variant<T>[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public byte[] IdentityByteArray(byte[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public boolean[] IdentityBoolArray(boolean[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public short[] IdentityInt16Array(short[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt16[] IdentityUInt16Array(UInt16[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public int[] IdentityInt32Array(int[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt32[] IdentityUInt32Array(UInt32[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public long[] IdentityInt64Array(long[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public UInt64[] IdentityUInt64Array(UInt64[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public double[] IdentityDoubleArray(double[] input);
|
||||
|
||||
@Description("Returns whatever it is passed")
|
||||
public String[] IdentityStringArray(String[] input);
|
||||
|
||||
@Description("Returns the sum of the values in the input list")
|
||||
public long Sum(int[] a);
|
||||
|
||||
@Description("Given a map of A => B, should return a map of B => a list of all the As which mapped to B")
|
||||
public Map<String, List<String>> InvertMapping(Map<String, String> a);
|
||||
|
||||
@Description("This method returns the contents of a struct as separate values")
|
||||
public Triplet<String, UInt32, Short> DeStruct(TestStruct a);
|
||||
|
||||
@Description("Given any compound type as a variant, return all the primitive types recursively contained within as an array of variants")
|
||||
public List<Variant<Object>> Primitize(Variant<Object> a);
|
||||
|
||||
@Description("inverts it's input")
|
||||
public boolean Invert(boolean a);
|
||||
|
||||
@Description("triggers sending of a signal from the supplied object with the given parameter")
|
||||
public void Trigger(String a, UInt64 b);
|
||||
|
||||
@Description("Causes the server to exit")
|
||||
public void Exit();
|
||||
}
|
||||
|
||||
public interface TestSignals extends DBusInterface {
|
||||
@Description("Sent in response to a method call")
|
||||
public static class Triggered extends DBusSignal {
|
||||
public final UInt64 a;
|
||||
|
||||
public Triggered(String path, UInt64 a) throws DBusException {
|
||||
super(path, a);
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class Triplet<A, B, C> extends Tuple {
|
||||
@Position(0)
|
||||
public final A a;
|
||||
@Position(1)
|
||||
public final B b;
|
||||
@Position(2)
|
||||
public final C c;
|
||||
|
||||
public Triplet(A a, B b, C c) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
}
|
||||
}
|
||||
|
||||
public final class TestStruct extends Struct {
|
||||
@Position(0)
|
||||
public final String a;
|
||||
@Position(1)
|
||||
public final UInt32 b;
|
||||
@Position(2)
|
||||
public final Short c;
|
||||
|
||||
public TestStruct(String a, UInt32 b, Short c) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
class ArrayFrob {
|
||||
static Hashtable<Class<? extends Object>, Class<? extends Object>> primitiveToWrapper = new Hashtable<Class<? extends Object>, Class<? extends Object>>();
|
||||
static Hashtable<Class<? extends Object>, Class<? extends Object>> wrapperToPrimitive = new Hashtable<Class<? extends Object>, Class<? extends Object>>();
|
||||
|
||||
static {
|
||||
primitiveToWrapper.put(Boolean.TYPE, Boolean.class);
|
||||
primitiveToWrapper.put(Byte.TYPE, Byte.class);
|
||||
primitiveToWrapper.put(Short.TYPE, Short.class);
|
||||
primitiveToWrapper.put(Character.TYPE, Character.class);
|
||||
primitiveToWrapper.put(Integer.TYPE, Integer.class);
|
||||
primitiveToWrapper.put(Long.TYPE, Long.class);
|
||||
primitiveToWrapper.put(Float.TYPE, Float.class);
|
||||
primitiveToWrapper.put(Double.TYPE, Double.class);
|
||||
wrapperToPrimitive.put(Boolean.class, Boolean.TYPE);
|
||||
wrapperToPrimitive.put(Byte.class, Byte.TYPE);
|
||||
wrapperToPrimitive.put(Short.class, Short.TYPE);
|
||||
wrapperToPrimitive.put(Character.class, Character.TYPE);
|
||||
wrapperToPrimitive.put(Integer.class, Integer.TYPE);
|
||||
wrapperToPrimitive.put(Long.class, Long.TYPE);
|
||||
wrapperToPrimitive.put(Float.class, Float.TYPE);
|
||||
wrapperToPrimitive.put(Double.class, Double.TYPE);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] wrap(Object o) throws IllegalArgumentException {
|
||||
Class<? extends Object> ac = o.getClass();
|
||||
if (!ac.isArray()) throw new IllegalArgumentException(getString("invalidArray"));
|
||||
Class<? extends Object> cc = ac.getComponentType();
|
||||
Class<? extends Object> ncc = primitiveToWrapper.get(cc);
|
||||
if (null == ncc) throw new IllegalArgumentException(getString("notPrimitiveType"));
|
||||
T[] ns = (T[]) Array.newInstance(ncc, Array.getLength(o));
|
||||
for (int i = 0; i < ns.length; i++)
|
||||
ns[i] = (T) Array.get(o, i);
|
||||
return ns;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Object unwrap(T[] ns) throws IllegalArgumentException {
|
||||
Class<? extends T[]> ac = (Class<? extends T[]>) ns.getClass();
|
||||
Class<T> cc = (Class<T>) ac.getComponentType();
|
||||
Class<? extends Object> ncc = wrapperToPrimitive.get(cc);
|
||||
if (null == ncc) throw new IllegalArgumentException(getString("invalidWrapperType"));
|
||||
Object o = Array.newInstance(ncc, ns.length);
|
||||
for (int i = 0; i < ns.length; i++)
|
||||
Array.set(o, i, ns[i]);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static <T> List<T> listify(T[] ns) throws IllegalArgumentException {
|
||||
return Arrays.asList(ns);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> listify(Object o) throws IllegalArgumentException {
|
||||
if (o instanceof Object[]) return listify((T[]) o);
|
||||
if (!o.getClass().isArray()) throw new IllegalArgumentException(getString("invalidArray"));
|
||||
List<T> l = new ArrayList<T>(Array.getLength(o));
|
||||
for (int i = 0; i < Array.getLength(o); i++)
|
||||
l.add((T) Array.get(o, i));
|
||||
return l;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] delist(List<T> l, Class<T> c) throws IllegalArgumentException {
|
||||
return l.toArray((T[]) Array.newInstance(c, 0));
|
||||
}
|
||||
|
||||
public static <T> Object delistprimitive(List<T> l, Class<T> c) throws IllegalArgumentException {
|
||||
Object o = Array.newInstance(c, l.size());
|
||||
for (int i = 0; i < l.size(); i++)
|
||||
Array.set(o, i, l.get(i));
|
||||
return o;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object convert(Object o, Class<? extends Object> c) throws IllegalArgumentException {
|
||||
/* Possible Conversions:
|
||||
*
|
||||
** List<Integer> -> List<Integer>
|
||||
** List<Integer> -> int[]
|
||||
** List<Integer> -> Integer[]
|
||||
** int[] -> int[]
|
||||
** int[] -> List<Integer>
|
||||
** int[] -> Integer[]
|
||||
** Integer[] -> Integer[]
|
||||
** Integer[] -> int[]
|
||||
** Integer[] -> List<Integer>
|
||||
*/
|
||||
try {
|
||||
// List<Integer> -> List<Integer>
|
||||
if (List.class.equals(c)
|
||||
&& o instanceof List)
|
||||
return o;
|
||||
|
||||
// int[] -> List<Integer>
|
||||
// Integer[] -> List<Integer>
|
||||
if (List.class.equals(c)
|
||||
&& o.getClass().isArray())
|
||||
return listify(o);
|
||||
|
||||
// int[] -> int[]
|
||||
// Integer[] -> Integer[]
|
||||
if (o.getClass().isArray()
|
||||
&& c.isArray()
|
||||
&& o.getClass().getComponentType().equals(c.getComponentType()))
|
||||
return o;
|
||||
|
||||
// int[] -> Integer[]
|
||||
if (o.getClass().isArray()
|
||||
&& c.isArray()
|
||||
&& o.getClass().getComponentType().isPrimitive())
|
||||
return wrap(o);
|
||||
|
||||
// Integer[] -> int[]
|
||||
if (o.getClass().isArray()
|
||||
&& c.isArray()
|
||||
&& c.getComponentType().isPrimitive())
|
||||
return unwrap((Object[]) o);
|
||||
|
||||
// List<Integer> -> int[]
|
||||
if (o instanceof List
|
||||
&& c.isArray()
|
||||
&& c.getComponentType().isPrimitive())
|
||||
return delistprimitive((List<Object>) o, (Class<Object>) c.getComponentType());
|
||||
|
||||
// List<Integer> -> Integer[]
|
||||
if (o instanceof List
|
||||
&& c.isArray())
|
||||
return delist((List<Object>) o, (Class<Object>) c.getComponentType());
|
||||
|
||||
if (o.getClass().isArray()
|
||||
&& c.isArray())
|
||||
return type((Object[]) o, (Class<Object>) c.getComponentType());
|
||||
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(MessageFormat.format(getString("convertionTypeNotExpected"), new Object[]{o.getClass(), c}));
|
||||
}
|
||||
|
||||
public static Object[] type(Object[] old, Class<Object> c) {
|
||||
Object[] ns = (Object[]) Array.newInstance(c, old.length);
|
||||
for (int i = 0; i < ns.length; i++)
|
||||
ns[i] = old[i];
|
||||
return ns;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class BusAddress {
|
||||
private String type;
|
||||
private Map<String, String> parameters;
|
||||
|
||||
public BusAddress(String address) throws ParseException {
|
||||
if (null == address || "".equals(address)) throw new ParseException(getString("busAddressBlank"), 0);
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Parsing bus address: " + address);
|
||||
String[] ss = address.split(":", 2);
|
||||
if (ss.length < 2) throw new ParseException(getString("busAddressInvalid") + address, 0);
|
||||
type = ss[0];
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Transport type: " + type);
|
||||
String[] ps = ss[1].split(",");
|
||||
parameters = new HashMap<String, String>();
|
||||
for (String p : ps) {
|
||||
String[] kv = p.split("=", 2);
|
||||
parameters.put(kv[0], kv[1]);
|
||||
}
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Transport options: " + parameters);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getParameter(String key) {
|
||||
return parameters.get(key);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + ": " + parameters;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
|
||||
/**
|
||||
* Interface for callbacks in async mode
|
||||
*/
|
||||
public interface CallbackHandler<ReturnType> {
|
||||
public void handle(ReturnType r);
|
||||
|
||||
public void handleError(DBusExecutionException e);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class is the super class of both Structs and Tuples
|
||||
* and holds common methods.
|
||||
*/
|
||||
abstract class Container {
|
||||
private static Map<Type, Type[]> typecache = new HashMap<Type, Type[]>();
|
||||
|
||||
static void putTypeCache(Type k, Type[] v) {
|
||||
typecache.put(k, v);
|
||||
}
|
||||
|
||||
static Type[] getTypeCache(Type k) {
|
||||
return typecache.get(k);
|
||||
}
|
||||
|
||||
private Object[] parameters = null;
|
||||
|
||||
public Container() {
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
Field[] fs = getClass().getDeclaredFields();
|
||||
Object[] args = new Object[fs.length];
|
||||
|
||||
int diff = 0;
|
||||
for (Field f : fs) {
|
||||
Position p = f.getAnnotation(Position.class);
|
||||
if (null == p) {
|
||||
diff++;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
args[p.value()] = f.get(this);
|
||||
} catch (IllegalAccessException IAe) {
|
||||
}
|
||||
}
|
||||
|
||||
this.parameters = new Object[args.length - diff];
|
||||
System.arraycopy(args, 0, parameters, 0, parameters.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the struct contents in order.
|
||||
*
|
||||
* @throws DBusException If there is a problem doing this.
|
||||
*/
|
||||
public final Object[] getParameters() {
|
||||
if (null != parameters) return parameters;
|
||||
setup();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this struct as a string.
|
||||
*/
|
||||
public final String toString() {
|
||||
String s = getClass().getName() + "<";
|
||||
if (null == parameters)
|
||||
setup();
|
||||
if (0 == parameters.length)
|
||||
return s + ">";
|
||||
for (Object o : parameters)
|
||||
s += o + ", ";
|
||||
return s.replaceAll(", $", ">");
|
||||
}
|
||||
|
||||
public final boolean equals(Object other) {
|
||||
if (other instanceof Container) {
|
||||
Container that = (Container) other;
|
||||
if (this.getClass().equals(that.getClass()))
|
||||
return Arrays.equals(this.getParameters(), that.getParameters());
|
||||
else return false;
|
||||
} else return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.DBus.Error.NoReply;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* A handle to an asynchronous method call.
|
||||
*/
|
||||
public class DBusAsyncReply<ReturnType> {
|
||||
/**
|
||||
* Check if any of a set of asynchronous calls have had a reply.
|
||||
*
|
||||
* @param replies A Collection of handles to replies to check.
|
||||
* @return A Collection only containing those calls which have had replies.
|
||||
*/
|
||||
public static Collection<DBusAsyncReply<? extends Object>> hasReply(Collection<DBusAsyncReply<? extends Object>> replies) {
|
||||
Collection<DBusAsyncReply<? extends Object>> c = new ArrayList<DBusAsyncReply<? extends Object>>(replies);
|
||||
Iterator<DBusAsyncReply<? extends Object>> i = c.iterator();
|
||||
while (i.hasNext())
|
||||
if (!i.next().hasReply()) i.remove();
|
||||
return c;
|
||||
}
|
||||
|
||||
private ReturnType rval = null;
|
||||
private DBusExecutionException error = null;
|
||||
private MethodCall mc;
|
||||
private Method me;
|
||||
private AbstractConnection conn;
|
||||
|
||||
DBusAsyncReply(MethodCall mc, Method me, AbstractConnection conn) {
|
||||
this.mc = mc;
|
||||
this.me = me;
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private synchronized void checkReply() {
|
||||
if (mc.hasReply()) {
|
||||
Message m = mc.getReply();
|
||||
if (m instanceof Error)
|
||||
error = ((Error) m).getException();
|
||||
else if (m instanceof MethodReturn) {
|
||||
try {
|
||||
rval = (ReturnType) RemoteInvocationHandler.convertRV(m.getSig(), m.getParameters(), me, conn);
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
error = DBEe;
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
error = new DBusExecutionException(DBe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we've had a reply.
|
||||
*
|
||||
* @return True if we have a reply
|
||||
*/
|
||||
public boolean hasReply() {
|
||||
if (null != rval || null != error) return true;
|
||||
checkReply();
|
||||
return null != rval || null != error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reply.
|
||||
*
|
||||
* @return The return value from the method.
|
||||
* @throws DBusExecutionException if the reply to the method was an error.
|
||||
* @throws NoReply if the method hasn't had a reply yet
|
||||
*/
|
||||
public ReturnType getReply() throws DBusExecutionException {
|
||||
if (null != rval) return rval;
|
||||
else if (null != error) throw error;
|
||||
checkReply();
|
||||
if (null != rval) return rval;
|
||||
else if (null != error) throw error;
|
||||
else throw new NoReply(getString("asyncCallNoReply"));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getString("waitingFor") + mc;
|
||||
}
|
||||
|
||||
Method getMethod() {
|
||||
return me;
|
||||
}
|
||||
|
||||
AbstractConnection getConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
MethodCall getCall() {
|
||||
return mc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* Holds information on a method call
|
||||
*/
|
||||
public class DBusCallInfo {
|
||||
/**
|
||||
* Indicates the caller won't wait for a reply (and we won't send one).
|
||||
*/
|
||||
public static final int NO_REPLY = Message.Flags.NO_REPLY_EXPECTED;
|
||||
public static final int ASYNC = 0x100;
|
||||
private String source;
|
||||
private String destination;
|
||||
private String objectpath;
|
||||
private String iface;
|
||||
private String method;
|
||||
private int flags;
|
||||
|
||||
DBusCallInfo(Message m) {
|
||||
this.source = m.getSource();
|
||||
this.destination = m.getDestination();
|
||||
this.objectpath = m.getPath();
|
||||
this.iface = m.getInterface();
|
||||
this.method = m.getName();
|
||||
this.flags = m.getFlags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BusID which called the method
|
||||
*/
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name with which we were addressed on the Bus
|
||||
*/
|
||||
public String getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object path used to call this method
|
||||
*/
|
||||
public String getObjectPath() {
|
||||
return objectpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface this method was called with
|
||||
*/
|
||||
public String getInterface() {
|
||||
return iface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the method name used to call this method
|
||||
*/
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any flags set on this method call
|
||||
*/
|
||||
public int getFlags() {
|
||||
return flags;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,794 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.DBus;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
import org.freedesktop.dbus.exceptions.NotConnected;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Handles a connection to DBus.
|
||||
* <p>
|
||||
* This is a Singleton class, only 1 connection to the SYSTEM or SESSION busses can be made.
|
||||
* Repeated calls to getConnection will return the same reference.
|
||||
* </p>
|
||||
* <p>
|
||||
* Signal Handlers and method calls from remote objects are run in their own threads, you MUST handle the concurrency issues.
|
||||
* </p>
|
||||
*/
|
||||
public class DBusConnection extends AbstractConnection {
|
||||
/**
|
||||
* Add addresses of peers to a set which will watch for them to
|
||||
* disappear and automatically remove them from the set.
|
||||
*/
|
||||
public class PeerSet implements Set<String>, DBusSigHandler<DBus.NameOwnerChanged> {
|
||||
private Set<String> addresses;
|
||||
|
||||
public PeerSet() {
|
||||
addresses = new TreeSet<String>();
|
||||
try {
|
||||
addSigHandler(new DBusMatchRule(DBus.NameOwnerChanged.class, null, null), this);
|
||||
} catch (DBusException DBe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
}
|
||||
}
|
||||
|
||||
public void handle(DBus.NameOwnerChanged noc) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Received NameOwnerChanged(" + noc.name + "," + noc.old_owner + "," + noc.new_owner + ")");
|
||||
if ("".equals(noc.new_owner) && addresses.contains(noc.name))
|
||||
remove(noc.name);
|
||||
}
|
||||
|
||||
public boolean add(String address) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Adding " + address);
|
||||
synchronized (addresses) {
|
||||
return addresses.add(address);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends String> addresses) {
|
||||
synchronized (this.addresses) {
|
||||
return this.addresses.addAll(addresses);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
synchronized (addresses) {
|
||||
addresses.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return addresses.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> os) {
|
||||
return addresses.containsAll(os);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof PeerSet)
|
||||
return ((PeerSet) o).addresses.equals(addresses);
|
||||
else return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return addresses.hashCode();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return addresses.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<String> iterator() {
|
||||
return addresses.iterator();
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Removing " + o);
|
||||
synchronized (addresses) {
|
||||
return addresses.remove(o);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> os) {
|
||||
synchronized (addresses) {
|
||||
return addresses.removeAll(os);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> os) {
|
||||
synchronized (addresses) {
|
||||
return addresses.retainAll(os);
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return addresses.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
synchronized (addresses) {
|
||||
return addresses.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
synchronized (addresses) {
|
||||
return addresses.toArray(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class _sighandler implements DBusSigHandler<DBusSignal> {
|
||||
public void handle(DBusSignal s) {
|
||||
if (s instanceof org.freedesktop.DBus.Local.Disconnected) {
|
||||
if (Debug.debug) Debug.print(Debug.WARN, "Handling disconnected signal from bus");
|
||||
try {
|
||||
Error err = new Error(
|
||||
"org.freedesktop.DBus.Local", "org.freedesktop.DBus.Local.disconnected", 0, "s", new Object[]{getString("disconnected")});
|
||||
if (null != pendingCalls) synchronized (pendingCalls) {
|
||||
long[] set = pendingCalls.getKeys();
|
||||
for (long l : set)
|
||||
if (-1 != l) {
|
||||
MethodCall m = pendingCalls.remove(l);
|
||||
if (null != m)
|
||||
m.setReply(err);
|
||||
}
|
||||
}
|
||||
synchronized (pendingErrors) {
|
||||
pendingErrors.add(err);
|
||||
}
|
||||
} catch (DBusException DBe) {
|
||||
}
|
||||
} else if (s instanceof org.freedesktop.DBus.NameAcquired) {
|
||||
busnames.add(((org.freedesktop.DBus.NameAcquired) s).name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* System Bus
|
||||
*/
|
||||
public static final int SYSTEM = 0;
|
||||
/**
|
||||
* Session Bus
|
||||
*/
|
||||
public static final int SESSION = 1;
|
||||
|
||||
public static final String DEFAULT_SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket";
|
||||
|
||||
private List<String> busnames;
|
||||
|
||||
private static final Map<Object, DBusConnection> conn = new HashMap<Object, DBusConnection>();
|
||||
private int _refcount = 0;
|
||||
private Object _reflock = new Object();
|
||||
private DBus _dbus;
|
||||
|
||||
/**
|
||||
* Connect to the BUS. If a connection already exists to the specified Bus, a reference to it is returned.
|
||||
*
|
||||
* @param address The address of the bus to connect to
|
||||
* @throws DBusException If there is a problem connecting to the Bus.
|
||||
*/
|
||||
public static DBusConnection getConnection(String address) throws DBusException {
|
||||
synchronized (conn) {
|
||||
DBusConnection c = conn.get(address);
|
||||
if (null != c) {
|
||||
synchronized (c._reflock) {
|
||||
c._refcount++;
|
||||
}
|
||||
return c;
|
||||
} else {
|
||||
c = new DBusConnection(address);
|
||||
conn.put(address, c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the BUS. If a connection already exists to the specified Bus, a reference to it is returned.
|
||||
*
|
||||
* @param bustype The Bus to connect to.
|
||||
* @throws DBusException If there is a problem connecting to the Bus.
|
||||
* @see #SYSTEM
|
||||
* @see #SESSION
|
||||
*/
|
||||
public static DBusConnection getConnection(int bustype) throws DBusException {
|
||||
synchronized (conn) {
|
||||
String s = null;
|
||||
switch (bustype) {
|
||||
case SYSTEM:
|
||||
s = System.getenv("DBUS_SYSTEM_BUS_ADDRESS");
|
||||
if (null == s) s = DEFAULT_SYSTEM_BUS_ADDRESS;
|
||||
break;
|
||||
case SESSION:
|
||||
s = System.getenv("DBUS_SESSION_BUS_ADDRESS");
|
||||
if (null == s) {
|
||||
// address gets stashed in $HOME/.dbus/session-bus/`dbus-uuidgen --get`-`sed 's/:\(.\)\..*/\1/' <<< $DISPLAY`
|
||||
String display = System.getenv("DISPLAY");
|
||||
if (null == display) throw new DBusException(getString("cannotResolveSessionBusAddress"));
|
||||
File uuidfile = new File("/var/lib/dbus/machine-id");
|
||||
if (!uuidfile.exists()) throw new DBusException(getString("cannotResolveSessionBusAddress"));
|
||||
try {
|
||||
BufferedReader r = new BufferedReader(new FileReader(uuidfile));
|
||||
String uuid = r.readLine();
|
||||
String homedir = System.getProperty("user.home");
|
||||
File addressfile = new File(homedir + "/.dbus/session-bus",
|
||||
uuid + "-" + display.replaceAll(":([0-9]*)\\..*", "$1"));
|
||||
if (!addressfile.exists())
|
||||
throw new DBusException(getString("cannotResolveSessionBusAddress"));
|
||||
r = new BufferedReader(new FileReader(addressfile));
|
||||
String l;
|
||||
while (null != (l = r.readLine())) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Reading D-Bus session data: " + l);
|
||||
if (l.matches("DBUS_SESSION_BUS_ADDRESS.*")) {
|
||||
s = l.replaceAll("^[^=]*=", "");
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Parsing " + l + " to " + s);
|
||||
}
|
||||
}
|
||||
if (null == s || "".equals(s))
|
||||
throw new DBusException(getString("cannotResolveSessionBusAddress"));
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.INFO, "Read bus address " + s + " from file " + addressfile.toString());
|
||||
} catch (Exception e) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusException(getString("cannotResolveSessionBusAddress"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new DBusException(getString("invalidBusType") + bustype);
|
||||
}
|
||||
DBusConnection c = conn.get(s);
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Getting bus connection for " + s + ": " + c);
|
||||
if (null != c) {
|
||||
synchronized (c._reflock) {
|
||||
c._refcount++;
|
||||
}
|
||||
return c;
|
||||
} else {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Creating new bus connection to: " + s);
|
||||
c = new DBusConnection(s);
|
||||
conn.put(s, c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DBusConnection(String address) throws DBusException {
|
||||
super(address);
|
||||
busnames = new Vector<String>();
|
||||
|
||||
synchronized (_reflock) {
|
||||
_refcount = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
transport = new Transport(addr, AbstractConnection.TIMEOUT);
|
||||
connected = true;
|
||||
} catch (IOException IOe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
|
||||
disconnect();
|
||||
throw new DBusException(getString("connectionFailure") + IOe.getMessage());
|
||||
} catch (ParseException Pe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, Pe);
|
||||
disconnect();
|
||||
throw new DBusException(getString("connectionFailure") + Pe.getMessage());
|
||||
}
|
||||
|
||||
// start listening for calls
|
||||
listen();
|
||||
|
||||
// register disconnect handlers
|
||||
DBusSigHandler h = new _sighandler();
|
||||
addSigHandlerWithoutMatch(org.freedesktop.DBus.Local.Disconnected.class, h);
|
||||
addSigHandlerWithoutMatch(org.freedesktop.DBus.NameAcquired.class, h);
|
||||
|
||||
// register ourselves
|
||||
_dbus = getRemoteObject("org.freedesktop.DBus", "/org/freedesktop/DBus", DBus.class);
|
||||
try {
|
||||
busnames.add(_dbus.Hello());
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
|
||||
throw new DBusException(DBEe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DBusInterface dynamicProxy(String source, String path) throws DBusException {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.INFO, "Introspecting " + path + " on " + source + " for dynamic proxy creation");
|
||||
try {
|
||||
DBus.Introspectable intro = getRemoteObject(source, path, DBus.Introspectable.class);
|
||||
String data = intro.Introspect();
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Got introspection data: " + data);
|
||||
String[] tags = data.split("[<>]");
|
||||
Vector<String> ifaces = new Vector<String>();
|
||||
for (String tag : tags) {
|
||||
if (tag.startsWith("interface")) {
|
||||
ifaces.add(tag.replaceAll("^interface *name *= *['\"]([^'\"]*)['\"].*$", "$1"));
|
||||
}
|
||||
}
|
||||
Vector<Class<? extends Object>> ifcs = new Vector<Class<? extends Object>>();
|
||||
for (String iface : ifaces) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Trying interface " + iface);
|
||||
int j = 0;
|
||||
while (j >= 0) {
|
||||
try {
|
||||
Class ifclass = Class.forName(iface);
|
||||
if (!ifcs.contains(ifclass))
|
||||
ifcs.add(ifclass);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
j = iface.lastIndexOf(".");
|
||||
char[] cs = iface.toCharArray();
|
||||
if (j >= 0) {
|
||||
cs[j] = '$';
|
||||
iface = String.valueOf(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ifcs.size() == 0) throw new DBusException(getString("interfaceToCastNotFound"));
|
||||
|
||||
RemoteObject ro = new RemoteObject(source, path, null, false);
|
||||
DBusInterface newi = (DBusInterface)
|
||||
Proxy.newProxyInstance(ifcs.get(0).getClassLoader(),
|
||||
ifcs.toArray(new Class[0]),
|
||||
new RemoteInvocationHandler(this, ro));
|
||||
importedObjects.put(newi, ro);
|
||||
return newi;
|
||||
} catch (Exception e) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusException(MessageFormat.format(getString("createProxyExportFailure"), new Object[]{path, source, e.getMessage()}));
|
||||
}
|
||||
}
|
||||
|
||||
DBusInterface getExportedObject(String source, String path) throws DBusException {
|
||||
ExportedObject o = null;
|
||||
synchronized (exportedObjects) {
|
||||
o = exportedObjects.get(path);
|
||||
}
|
||||
if (null != o && null == o.object.get()) {
|
||||
unExportObject(path);
|
||||
o = null;
|
||||
}
|
||||
if (null != o) return o.object.get();
|
||||
if (null == source) throw new DBusException(getString("objectNotExportedNoRemoteSpecified"));
|
||||
return dynamicProxy(source, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release a bus name.
|
||||
* Releases the name so that other people can use it
|
||||
*
|
||||
* @param busname The name to release. MUST be in dot-notation like "org.freedesktop.local"
|
||||
* @throws DBusException If the busname is incorrectly formatted.
|
||||
*/
|
||||
public void releaseBusName(String busname) throws DBusException {
|
||||
if (!busname.matches(BUSNAME_REGEX) || busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName"));
|
||||
synchronized (this.busnames) {
|
||||
UInt32 rv;
|
||||
try {
|
||||
rv = _dbus.ReleaseName(busname);
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
|
||||
throw new DBusException(DBEe.getMessage());
|
||||
}
|
||||
this.busnames.remove(busname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a bus name.
|
||||
* Request the well known name that this should respond to on the Bus.
|
||||
*
|
||||
* @param busname The name to respond to. MUST be in dot-notation like "org.freedesktop.local"
|
||||
* @throws DBusException If the register name failed, or our name already exists on the bus.
|
||||
* or if busname is incorrectly formatted.
|
||||
*/
|
||||
public void requestBusName(String busname) throws DBusException {
|
||||
if (!busname.matches(BUSNAME_REGEX) || busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName"));
|
||||
synchronized (this.busnames) {
|
||||
UInt32 rv;
|
||||
try {
|
||||
rv = _dbus.RequestName(busname,
|
||||
new UInt32(DBus.DBUS_NAME_FLAG_REPLACE_EXISTING |
|
||||
DBus.DBUS_NAME_FLAG_DO_NOT_QUEUE));
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
|
||||
throw new DBusException(DBEe.getMessage());
|
||||
}
|
||||
switch (rv.intValue()) {
|
||||
case DBus.DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
|
||||
break;
|
||||
case DBus.DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
|
||||
throw new DBusException(getString("dbusRegistrationFailure"));
|
||||
case DBus.DBUS_REQUEST_NAME_REPLY_EXISTS:
|
||||
throw new DBusException(getString("dbusRegistrationFailure"));
|
||||
case DBus.DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.busnames.add(busname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique name of this connection.
|
||||
*/
|
||||
public String getUniqueName() {
|
||||
return busnames.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the names owned by this connection.
|
||||
*/
|
||||
public String[] getNames() {
|
||||
Set<String> names = new TreeSet<String>();
|
||||
names.addAll(busnames);
|
||||
return names.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public <I extends DBusInterface> I getPeerRemoteObject(String busname, String objectpath, Class<I> type) throws DBusException {
|
||||
return getPeerRemoteObject(busname, objectpath, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to a remote object.
|
||||
* This method will resolve the well known name (if given) to a unique bus name when you call it.
|
||||
* This means that if a well known name is released by one process and acquired by another calls to
|
||||
* objects gained from this method will continue to operate on the original process.
|
||||
* <p>
|
||||
* This method will use bus introspection to determine the interfaces on a remote object and so
|
||||
* <b>may block</b> and <b>may fail</b>. The resulting proxy object will, however, be castable
|
||||
* to any interface it implements. It will also autostart the process if applicable. Also note
|
||||
* that the resulting proxy may fail to execute the correct method with overloaded methods
|
||||
* and that complex types may fail in interesting ways. Basically, if something odd happens,
|
||||
* try specifying the interface explicitly.
|
||||
*
|
||||
* @param busname The bus name to connect to. Usually a well known bus name in dot-notation (such as "org.freedesktop.local")
|
||||
* or may be a DBus address such as ":1-16".
|
||||
* @param objectpath The path on which the process is exporting the object.$
|
||||
* @return A reference to a remote object.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusInterface
|
||||
* @throws DBusException If busname or objectpath are incorrectly formatted.
|
||||
*/
|
||||
public DBusInterface getPeerRemoteObject(String busname, String objectpath) throws DBusException {
|
||||
if (null == busname) throw new DBusException(getString("nullBusName"));
|
||||
|
||||
if ((!busname.matches(BUSNAME_REGEX) && !busname.matches(CONNID_REGEX))
|
||||
|| busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + busname);
|
||||
|
||||
String unique = _dbus.GetNameOwner(busname);
|
||||
|
||||
return dynamicProxy(unique, objectpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to a remote object.
|
||||
* This method will always refer to the well known name (if given) rather than resolving it to a unique bus name.
|
||||
* In particular this means that if a process providing the well known name disappears and is taken over by another process
|
||||
* proxy objects gained by this method will make calls on the new proccess.
|
||||
* <p>
|
||||
* This method will use bus introspection to determine the interfaces on a remote object and so
|
||||
* <b>may block</b> and <b>may fail</b>. The resulting proxy object will, however, be castable
|
||||
* to any interface it implements. It will also autostart the process if applicable. Also note
|
||||
* that the resulting proxy may fail to execute the correct method with overloaded methods
|
||||
* and that complex types may fail in interesting ways. Basically, if something odd happens,
|
||||
* try specifying the interface explicitly.
|
||||
*
|
||||
* @param busname The bus name to connect to. Usually a well known bus name name in dot-notation (such as "org.freedesktop.local")
|
||||
* or may be a DBus address such as ":1-16".
|
||||
* @param objectpath The path on which the process is exporting the object.
|
||||
* @return A reference to a remote object.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusInterface
|
||||
* @throws DBusException If busname or objectpath are incorrectly formatted.
|
||||
*/
|
||||
public DBusInterface getRemoteObject(String busname, String objectpath) throws DBusException {
|
||||
if (null == busname) throw new DBusException(getString("nullBusName"));
|
||||
if (null == objectpath) throw new DBusException(getString("nullObjectPath"));
|
||||
|
||||
if ((!busname.matches(BUSNAME_REGEX) && !busname.matches(CONNID_REGEX))
|
||||
|| busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + busname);
|
||||
|
||||
if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidObjectPath") + objectpath);
|
||||
|
||||
return dynamicProxy(busname, objectpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to a remote object.
|
||||
* This method will resolve the well known name (if given) to a unique bus name when you call it.
|
||||
* This means that if a well known name is released by one process and acquired by another calls to
|
||||
* objects gained from this method will continue to operate on the original process.
|
||||
*
|
||||
* @param busname The bus name to connect to. Usually a well known bus name in dot-notation (such as "org.freedesktop.local")
|
||||
* or may be a DBus address such as ":1-16".
|
||||
* @param objectpath The path on which the process is exporting the object.$
|
||||
* @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
|
||||
* as the interface the remote object is exporting.
|
||||
* @param autostart Disable/Enable auto-starting of services in response to calls on this object.
|
||||
* Default is enabled; when calling a method with auto-start enabled, if the destination is a well-known name
|
||||
* and is not owned the bus will attempt to start a process to take the name. When disabled an error is
|
||||
* returned immediately.
|
||||
* @return A reference to a remote object.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusInterface
|
||||
* @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
|
||||
*/
|
||||
public <I extends DBusInterface> I getPeerRemoteObject(String busname, String objectpath, Class<I> type, boolean autostart) throws DBusException {
|
||||
if (null == busname) throw new DBusException(getString("nullBusName"));
|
||||
|
||||
if ((!busname.matches(BUSNAME_REGEX) && !busname.matches(CONNID_REGEX))
|
||||
|| busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + busname);
|
||||
|
||||
String unique = _dbus.GetNameOwner(busname);
|
||||
|
||||
return getRemoteObject(unique, objectpath, type, autostart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to a remote object.
|
||||
* This method will always refer to the well known name (if given) rather than resolving it to a unique bus name.
|
||||
* In particular this means that if a process providing the well known name disappears and is taken over by another process
|
||||
* proxy objects gained by this method will make calls on the new proccess.
|
||||
*
|
||||
* @param busname The bus name to connect to. Usually a well known bus name name in dot-notation (such as "org.freedesktop.local")
|
||||
* or may be a DBus address such as ":1-16".
|
||||
* @param objectpath The path on which the process is exporting the object.
|
||||
* @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
|
||||
* as the interface the remote object is exporting.
|
||||
* @return A reference to a remote object.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusInterface
|
||||
* @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
|
||||
*/
|
||||
public <I extends DBusInterface> I getRemoteObject(String busname, String objectpath, Class<I> type) throws DBusException {
|
||||
return getRemoteObject(busname, objectpath, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to a remote object.
|
||||
* This method will always refer to the well known name (if given) rather than resolving it to a unique bus name.
|
||||
* In particular this means that if a process providing the well known name disappears and is taken over by another process
|
||||
* proxy objects gained by this method will make calls on the new proccess.
|
||||
*
|
||||
* @param busname The bus name to connect to. Usually a well known bus name name in dot-notation (such as "org.freedesktop.local")
|
||||
* or may be a DBus address such as ":1-16".
|
||||
* @param objectpath The path on which the process is exporting the object.
|
||||
* @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
|
||||
* as the interface the remote object is exporting.
|
||||
* @param autostart Disable/Enable auto-starting of services in response to calls on this object.
|
||||
* Default is enabled; when calling a method with auto-start enabled, if the destination is a well-known name
|
||||
* and is not owned the bus will attempt to start a process to take the name. When disabled an error is
|
||||
* returned immediately.
|
||||
* @return A reference to a remote object.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusInterface
|
||||
* @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <I extends DBusInterface> I getRemoteObject(String busname, String objectpath, Class<I> type, boolean autostart) throws DBusException {
|
||||
if (null == busname) throw new DBusException(getString("nullBusName"));
|
||||
if (null == objectpath) throw new DBusException(getString("nullObjectPath"));
|
||||
if (null == type) throw new ClassCastException(getString("notDBusInterface"));
|
||||
|
||||
if ((!busname.matches(BUSNAME_REGEX) && !busname.matches(CONNID_REGEX))
|
||||
|| busname.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + busname);
|
||||
|
||||
if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidObjectPath") + objectpath);
|
||||
|
||||
if (!DBusInterface.class.isAssignableFrom(type)) throw new ClassCastException(getString("notDBusInterface"));
|
||||
|
||||
// don't let people import things which don't have a
|
||||
// valid D-Bus interface name
|
||||
if (type.getName().equals(type.getSimpleName()))
|
||||
throw new DBusException(getString("interfaceNotAllowedOutsidePackage"));
|
||||
|
||||
RemoteObject ro = new RemoteObject(busname, objectpath, type, autostart);
|
||||
I i = (I) Proxy.newProxyInstance(type.getClassLoader(),
|
||||
new Class[]{type}, new RemoteInvocationHandler(this, ro));
|
||||
importedObjects.put(i, ro);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Signal Handler.
|
||||
* Stops listening for this signal.
|
||||
*
|
||||
* @param type The signal to watch for.
|
||||
* @param source The source of the signal.
|
||||
* @throws DBusException If listening for the signal on the bus failed.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusSignal.
|
||||
*/
|
||||
public <T extends DBusSignal> void removeSigHandler(Class<T> type, String source, DBusSigHandler<T> handler) throws DBusException {
|
||||
if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException(getString("notDBusSignal"));
|
||||
if (source.matches(BUSNAME_REGEX)) throw new DBusException(getString("cannotWatchSignalsWellKnownBussName"));
|
||||
if (!source.matches(CONNID_REGEX) || source.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + source);
|
||||
removeSigHandler(new DBusMatchRule(type, source, null), handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Signal Handler.
|
||||
* Stops listening for this signal.
|
||||
*
|
||||
* @param type The signal to watch for.
|
||||
* @param source The source of the signal.
|
||||
* @param object The object emitting the signal.
|
||||
* @throws DBusException If listening for the signal on the bus failed.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusSignal.
|
||||
*/
|
||||
public <T extends DBusSignal> void removeSigHandler(Class<T> type, String source, DBusInterface object, DBusSigHandler<T> handler) throws DBusException {
|
||||
if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException(getString("notDBusSignal"));
|
||||
if (source.matches(BUSNAME_REGEX)) throw new DBusException(getString("cannotWatchSignalsWellKnownBussName"));
|
||||
if (!source.matches(CONNID_REGEX) || source.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + source);
|
||||
String objectpath = importedObjects.get(object).objectpath;
|
||||
if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidObjectPath") + objectpath);
|
||||
removeSigHandler(new DBusMatchRule(type, source, objectpath), handler);
|
||||
}
|
||||
|
||||
protected <T extends DBusSignal> void removeSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException {
|
||||
|
||||
SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
|
||||
synchronized (handledSignals) {
|
||||
Vector<DBusSigHandler<? extends DBusSignal>> v = handledSignals.get(key);
|
||||
if (null != v) {
|
||||
v.remove(handler);
|
||||
if (0 == v.size()) {
|
||||
handledSignals.remove(key);
|
||||
try {
|
||||
_dbus.RemoveMatch(rule.toString());
|
||||
} catch (NotConnected NC) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, NC);
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
|
||||
throw new DBusException(DBEe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Signal Handler.
|
||||
* Adds a signal handler to call when a signal is received which matches the specified type, name and source.
|
||||
*
|
||||
* @param type The signal to watch for.
|
||||
* @param source The process which will send the signal. This <b>MUST</b> be a unique bus name and not a well known name.
|
||||
* @param handler The handler to call when a signal is received.
|
||||
* @throws DBusException If listening for the signal on the bus failed.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusSignal.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DBusSignal> void addSigHandler(Class<T> type, String source, DBusSigHandler<T> handler) throws DBusException {
|
||||
if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException(getString("notDBusSignal"));
|
||||
if (source.matches(BUSNAME_REGEX)) throw new DBusException(getString("cannotWatchSignalsWellKnownBussName"));
|
||||
if (!source.matches(CONNID_REGEX) || source.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + source);
|
||||
addSigHandler(new DBusMatchRule(type, source, null), (DBusSigHandler<? extends DBusSignal>) handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Signal Handler.
|
||||
* Adds a signal handler to call when a signal is received which matches the specified type, name, source and object.
|
||||
*
|
||||
* @param type The signal to watch for.
|
||||
* @param source The process which will send the signal. This <b>MUST</b> be a unique bus name and not a well known name.
|
||||
* @param object The object from which the signal will be emitted
|
||||
* @param handler The handler to call when a signal is received.
|
||||
* @throws DBusException If listening for the signal on the bus failed.
|
||||
* @throws ClassCastException If type is not a sub-type of DBusSignal.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DBusSignal> void addSigHandler(Class<T> type, String source, DBusInterface object, DBusSigHandler<T> handler) throws DBusException {
|
||||
if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException(getString("notDBusSignal"));
|
||||
if (source.matches(BUSNAME_REGEX)) throw new DBusException(getString("cannotWatchSignalsWellKnownBussName"));
|
||||
if (!source.matches(CONNID_REGEX) || source.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidBusName") + source);
|
||||
String objectpath = importedObjects.get(object).objectpath;
|
||||
if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("invalidObjectPath") + objectpath);
|
||||
addSigHandler(new DBusMatchRule(type, source, objectpath), (DBusSigHandler<? extends DBusSignal>) handler);
|
||||
}
|
||||
|
||||
protected <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException {
|
||||
try {
|
||||
_dbus.AddMatch(rule.toString());
|
||||
} catch (DBusExecutionException DBEe) {
|
||||
if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
|
||||
throw new DBusException(DBEe.getMessage());
|
||||
}
|
||||
SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
|
||||
synchronized (handledSignals) {
|
||||
Vector<DBusSigHandler<? extends DBusSignal>> v = handledSignals.get(key);
|
||||
if (null == v) {
|
||||
v = new Vector<DBusSigHandler<? extends DBusSignal>>();
|
||||
v.add(handler);
|
||||
handledSignals.put(key, v);
|
||||
} else
|
||||
v.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the Bus.
|
||||
* This only disconnects when the last reference to the bus has disconnect called on it
|
||||
* or has been destroyed.
|
||||
*/
|
||||
public void disconnect() {
|
||||
synchronized (conn) {
|
||||
synchronized (_reflock) {
|
||||
if (0 == --_refcount) {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Disconnecting DBusConnection");
|
||||
// Set all pending messages to have an error.
|
||||
try {
|
||||
Error err = new Error(
|
||||
"org.freedesktop.DBus.Local", "org.freedesktop.DBus.Local.disconnected", 0, "s", new Object[]{getString("disconnected")});
|
||||
synchronized (pendingCalls) {
|
||||
long[] set = pendingCalls.getKeys();
|
||||
for (long l : set)
|
||||
if (-1 != l) {
|
||||
MethodCall m = pendingCalls.remove(l);
|
||||
if (null != m)
|
||||
m.setReply(err);
|
||||
}
|
||||
pendingCalls = null;
|
||||
}
|
||||
synchronized (pendingErrors) {
|
||||
pendingErrors.add(err);
|
||||
}
|
||||
} catch (DBusException DBe) {
|
||||
}
|
||||
|
||||
conn.remove(addr);
|
||||
super.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* Denotes a class as exportable or a remote interface which can be called.
|
||||
* <p>
|
||||
* Any interface which should be exported or imported should extend this
|
||||
* interface. All public methods from that interface are exported/imported
|
||||
* with the given method signatures.
|
||||
* </p>
|
||||
* <p>
|
||||
* All method calls on exported objects are run in their own threads.
|
||||
* Application writers are responsible for any concurrency issues.
|
||||
* </p>
|
||||
*/
|
||||
public interface DBusInterface {
|
||||
/**
|
||||
* Returns true on remote objects.
|
||||
* Local objects implementing this interface MUST return false.
|
||||
*/
|
||||
public boolean isRemote();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Force the interface name to be different to the Java class name.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface DBusInterfaceName {
|
||||
/**
|
||||
* The replacement interface name.
|
||||
*/
|
||||
String value();
|
||||
}
|
150
federation/sssd/src/main/java/org/freedesktop/dbus/DBusMap.java
Normal file
150
federation/sssd/src/main/java/org/freedesktop/dbus/DBusMap.java
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
|
||||
class DBusMap<K, V> implements Map<K, V> {
|
||||
Object[][] entries;
|
||||
|
||||
public DBusMap(Object[][] entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
class Entry implements Map.Entry<K, V>, Comparable<Entry> {
|
||||
private int entry;
|
||||
|
||||
public Entry(int i) {
|
||||
this.entry = i;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (null == o) return false;
|
||||
if (!(o instanceof DBusMap.Entry)) return false;
|
||||
return this.entry == ((Entry) o).entry;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public K getKey() {
|
||||
return (K) entries[entry][0];
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public V getValue() {
|
||||
return (V) entries[entry][1];
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return entries[entry][0].hashCode();
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int compareTo(Entry e) {
|
||||
return entry - e.entry;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
for (int i = 0; i < entries.length; i++)
|
||||
if (key == entries[i][0] || (key != null && key.equals(entries[i][0])))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
for (int i = 0; i < entries.length; i++)
|
||||
if (value == entries[i][1] || (value != null && value.equals(entries[i][1])))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
Set<Map.Entry<K, V>> s = new TreeSet<Map.Entry<K, V>>();
|
||||
for (int i = 0; i < entries.length; i++)
|
||||
s.add(new Entry(i));
|
||||
return s;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public V get(Object key) {
|
||||
for (int i = 0; i < entries.length; i++)
|
||||
if (key == entries[i][0] || (key != null && key.equals(entries[i][0])))
|
||||
return (V) entries[i][1];
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return entries.length == 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<K> keySet() {
|
||||
Set<K> s = new TreeSet<K>();
|
||||
for (Object[] entry : entries)
|
||||
s.add((K) entry[0]);
|
||||
return s;
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> t) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return entries.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<V> values() {
|
||||
List<V> l = new Vector<V>();
|
||||
for (Object[] entry : entries)
|
||||
l.add((V) entry[1]);
|
||||
return l;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Arrays.deepHashCode(entries);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean equals(Object o) {
|
||||
if (null == o) return false;
|
||||
if (!(o instanceof Map)) return false;
|
||||
return ((Map<K, V>) o).entrySet().equals(entrySet());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = "{ ";
|
||||
for (int i = 0; i < entries.length; i++)
|
||||
s += entries[i][0] + " => " + entries[i][1] + ",";
|
||||
return s.replaceAll(".$", " }");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class DBusMatchRule {
|
||||
/* signal, error, method_call, method_reply */
|
||||
private String type;
|
||||
private String iface;
|
||||
private String member;
|
||||
private String object;
|
||||
private String source;
|
||||
private static HashMap<String, Class<? extends DBusSignal>> signalTypeMap =
|
||||
new HashMap<String, Class<? extends DBusSignal>>();
|
||||
|
||||
static Class<? extends DBusSignal> getCachedSignalType(String type) {
|
||||
return signalTypeMap.get(type);
|
||||
}
|
||||
|
||||
public DBusMatchRule(String type, String iface, String member) {
|
||||
this.type = type;
|
||||
this.iface = iface;
|
||||
this.member = member;
|
||||
}
|
||||
|
||||
public DBusMatchRule(DBusExecutionException e) throws DBusException {
|
||||
this(e.getClass());
|
||||
member = null;
|
||||
type = "error";
|
||||
}
|
||||
|
||||
public DBusMatchRule(Message m) {
|
||||
iface = m.getInterface();
|
||||
member = m.getName();
|
||||
if (m instanceof DBusSignal)
|
||||
type = "signal";
|
||||
else if (m instanceof Error) {
|
||||
type = "error";
|
||||
member = null;
|
||||
} else if (m instanceof MethodCall)
|
||||
type = "method_call";
|
||||
else if (m instanceof MethodReturn)
|
||||
type = "method_reply";
|
||||
}
|
||||
|
||||
public DBusMatchRule(Class<? extends DBusInterface> c, String method) throws DBusException {
|
||||
this(c);
|
||||
member = method;
|
||||
type = "method_call";
|
||||
}
|
||||
|
||||
public DBusMatchRule(Class<? extends Object> c, String source, String object) throws DBusException {
|
||||
this(c);
|
||||
this.source = source;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public DBusMatchRule(Class<? extends Object> c) throws DBusException {
|
||||
if (DBusInterface.class.isAssignableFrom(c)) {
|
||||
if (null != c.getAnnotation(DBusInterfaceName.class))
|
||||
iface = c.getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
iface = AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
|
||||
if (!iface.matches(".*\\..*"))
|
||||
throw new DBusException(getString("interfaceMustBeDefinedPackage"));
|
||||
member = null;
|
||||
type = null;
|
||||
} else if (DBusSignal.class.isAssignableFrom(c)) {
|
||||
if (null == c.getEnclosingClass())
|
||||
throw new DBusException(getString("signalsMustBeMemberOfClass"));
|
||||
else if (null != c.getEnclosingClass().getAnnotation(DBusInterfaceName.class))
|
||||
iface = c.getEnclosingClass().getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
iface = AbstractConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
|
||||
// Don't export things which are invalid D-Bus interfaces
|
||||
if (!iface.matches(".*\\..*"))
|
||||
throw new DBusException(getString("interfaceMustBeDefinedPackage"));
|
||||
if (c.isAnnotationPresent(DBusMemberName.class))
|
||||
member = c.getAnnotation(DBusMemberName.class).value();
|
||||
else
|
||||
member = c.getSimpleName();
|
||||
signalTypeMap.put(iface + '$' + member, (Class<? extends DBusSignal>) c);
|
||||
type = "signal";
|
||||
} else if (Error.class.isAssignableFrom(c)) {
|
||||
if (null != c.getAnnotation(DBusInterfaceName.class))
|
||||
iface = c.getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
iface = AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
|
||||
if (!iface.matches(".*\\..*"))
|
||||
throw new DBusException(getString("interfaceMustBeDefinedPackage"));
|
||||
member = null;
|
||||
type = "error";
|
||||
} else if (DBusExecutionException.class.isAssignableFrom(c)) {
|
||||
if (null != c.getClass().getAnnotation(DBusInterfaceName.class))
|
||||
iface = c.getClass().getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
iface = AbstractConnection.dollar_pattern.matcher(c.getClass().getName()).replaceAll(".");
|
||||
if (!iface.matches(".*\\..*"))
|
||||
throw new DBusException(getString("interfaceMustBeDefinedPackage"));
|
||||
member = null;
|
||||
type = "error";
|
||||
} else
|
||||
throw new DBusException(getString("invalidTypeMatchRule") + c);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = null;
|
||||
if (null != type) s = null == s ? "type='" + type + "'" : s + ",type='" + type + "'";
|
||||
if (null != member) s = null == s ? "member='" + member + "'" : s + ",member='" + member + "'";
|
||||
if (null != iface) s = null == s ? "interface='" + iface + "'" : s + ",interface='" + iface + "'";
|
||||
if (null != source) s = null == s ? "sender='" + source + "'" : s + ",sender='" + source + "'";
|
||||
if (null != object) s = null == s ? "path='" + object + "'" : s + ",path='" + object + "'";
|
||||
return s;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getInterface() {
|
||||
return iface;
|
||||
}
|
||||
|
||||
public String getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public String getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Force the member (method/signal) name on the bus to be different to the Java name.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
public @interface DBusMemberName {
|
||||
/**
|
||||
* The replacement member name.
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
|
||||
/**
|
||||
* Custom classes may be sent over DBus if they implement this interface.
|
||||
* <p>
|
||||
* In addition to the serialize method, classes <b>MUST</b> implement
|
||||
* a deserialize method which returns null and takes as it's arguments
|
||||
* all the DBus types the class will be serialied to <i>in order</i> and
|
||||
* <i>with type parameterisation</i>. They <b>MUST</b> also provide a
|
||||
* zero-argument constructor.
|
||||
* </p>
|
||||
* <p>
|
||||
* The serialize method should return the class properties you wish to
|
||||
* serialize, correctly formatted for the wire
|
||||
* (DBusConnection.convertParameters() can help with this), in order in an
|
||||
* Object array.
|
||||
* </p>
|
||||
* <p>
|
||||
* The deserialize method will be called once after the zero-argument
|
||||
* constructor. This should contain all the code to initialise the object
|
||||
* from the types.
|
||||
* </p>
|
||||
*/
|
||||
public interface DBusSerializable {
|
||||
public Object[] serialize() throws DBusException;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* Handle a signal on DBus.
|
||||
* All Signal handlers are run in their own Thread.
|
||||
* Application writers are responsible for managing any concurrency issues.
|
||||
*/
|
||||
public interface DBusSigHandler<T extends DBusSignal> {
|
||||
/**
|
||||
* Handle a signal.
|
||||
*
|
||||
* @param s The signal to handle. If such a class exists, the
|
||||
* signal will be an instance of the class with the correct type signature.
|
||||
* Otherwise it will be an instance of DBusSignal
|
||||
*/
|
||||
public void handle(T s);
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.MessageFormatException;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.GenericDeclaration;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class DBusSignal extends Message {
|
||||
DBusSignal() {
|
||||
}
|
||||
|
||||
public DBusSignal(String source, String path, String iface, String member, String sig, Object... args) throws DBusException {
|
||||
super(Message.Endian.BIG, Message.MessageType.SIGNAL, (byte) 0);
|
||||
|
||||
if (null == path || null == member || null == iface)
|
||||
throw new MessageFormatException(getString("missingPathInterfaceSignal"));
|
||||
headers.put(Message.HeaderField.PATH, path);
|
||||
headers.put(Message.HeaderField.MEMBER, member);
|
||||
headers.put(Message.HeaderField.INTERFACE, iface);
|
||||
|
||||
Vector<Object> hargs = new Vector<Object>();
|
||||
hargs.add(new Object[]{Message.HeaderField.PATH, new Object[]{ArgumentType.OBJECT_PATH_STRING, path}});
|
||||
hargs.add(new Object[]{Message.HeaderField.INTERFACE, new Object[]{ArgumentType.STRING_STRING, iface}});
|
||||
hargs.add(new Object[]{Message.HeaderField.MEMBER, new Object[]{ArgumentType.STRING_STRING, member}});
|
||||
|
||||
if (null != source) {
|
||||
headers.put(Message.HeaderField.SENDER, source);
|
||||
hargs.add(new Object[]{Message.HeaderField.SENDER, new Object[]{ArgumentType.STRING_STRING, source}});
|
||||
}
|
||||
|
||||
if (null != sig) {
|
||||
hargs.add(new Object[]{Message.HeaderField.SIGNATURE, new Object[]{ArgumentType.SIGNATURE_STRING, sig}});
|
||||
headers.put(Message.HeaderField.SIGNATURE, sig);
|
||||
setArgs(args);
|
||||
}
|
||||
|
||||
blen = new byte[4];
|
||||
appendBytes(blen);
|
||||
append("ua(yv)", ++serial, hargs.toArray());
|
||||
pad((byte) 8);
|
||||
|
||||
long c = bytecounter;
|
||||
if (null != sig) append(sig, args);
|
||||
marshallint(bytecounter - c, blen, 0, 4);
|
||||
bodydone = true;
|
||||
}
|
||||
|
||||
static class internalsig extends DBusSignal {
|
||||
public internalsig(String source, String objectpath, String type, String name, String sig, Object[] parameters, long serial) throws DBusException {
|
||||
super(source, objectpath, type, name, sig, parameters, serial);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<Class<? extends DBusSignal>, Type[]> typeCache = new HashMap<Class<? extends DBusSignal>, Type[]>();
|
||||
private static Map<String, Class<? extends DBusSignal>> classCache = new HashMap<String, Class<? extends DBusSignal>>();
|
||||
private static Map<Class<? extends DBusSignal>, Constructor<? extends DBusSignal>> conCache = new HashMap<Class<? extends DBusSignal>, Constructor<? extends DBusSignal>>();
|
||||
private static Map<String, String> signames = new HashMap<String, String>();
|
||||
private static Map<String, String> intnames = new HashMap<String, String>();
|
||||
private Class<? extends DBusSignal> c;
|
||||
private boolean bodydone = false;
|
||||
private byte[] blen;
|
||||
|
||||
static void addInterfaceMap(String java, String dbus) {
|
||||
intnames.put(dbus, java);
|
||||
}
|
||||
|
||||
static void addSignalMap(String java, String dbus) {
|
||||
signames.put(dbus, java);
|
||||
}
|
||||
|
||||
static DBusSignal createSignal(Class<? extends DBusSignal> c, String source, String objectpath, String sig, long serial, Object... parameters) throws DBusException {
|
||||
String type = "";
|
||||
if (null != c.getEnclosingClass()) {
|
||||
if (null != c.getEnclosingClass().getAnnotation(DBusInterfaceName.class))
|
||||
type = c.getEnclosingClass().getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
type = AbstractConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
|
||||
|
||||
} else
|
||||
throw new DBusException(getString("signalsMustBeMemberOfClass"));
|
||||
DBusSignal s = new internalsig(source, objectpath, type, c.getSimpleName(), sig, parameters, serial);
|
||||
s.c = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Class<? extends DBusSignal> createSignalClass(String intname, String signame) throws DBusException {
|
||||
String name = intname + '$' + signame;
|
||||
Class<? extends DBusSignal> c = classCache.get(name);
|
||||
if (null == c) c = DBusMatchRule.getCachedSignalType(name);
|
||||
if (null != c) return c;
|
||||
do {
|
||||
try {
|
||||
c = (Class<? extends DBusSignal>) Class.forName(name);
|
||||
} catch (ClassNotFoundException CNFe) {
|
||||
}
|
||||
name = name.replaceAll("\\.([^\\.]*)$", "\\$$1");
|
||||
} while (null == c && name.matches(".*\\..*"));
|
||||
if (null == c)
|
||||
throw new DBusException(getString("cannotCreateClassFromSignal") + intname + '.' + signame);
|
||||
classCache.put(name, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DBusSignal createReal(AbstractConnection conn) throws DBusException {
|
||||
String intname = intnames.get(getInterface());
|
||||
String signame = signames.get(getName());
|
||||
if (null == intname) intname = getInterface();
|
||||
if (null == signame) signame = getName();
|
||||
if (null == c)
|
||||
c = createSignalClass(intname, signame);
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Converting signal to type: " + c);
|
||||
Type[] types = typeCache.get(c);
|
||||
Constructor<? extends DBusSignal> con = conCache.get(c);
|
||||
if (null == types) {
|
||||
con = (Constructor<? extends DBusSignal>) c.getDeclaredConstructors()[0];
|
||||
conCache.put(c, con);
|
||||
Type[] ts = con.getGenericParameterTypes();
|
||||
types = new Type[ts.length - 1];
|
||||
for (int i = 1; i < ts.length; i++)
|
||||
if (ts[i] instanceof TypeVariable)
|
||||
for (Type b : ((TypeVariable<GenericDeclaration>) ts[i]).getBounds())
|
||||
types[i - 1] = b;
|
||||
else
|
||||
types[i - 1] = ts[i];
|
||||
typeCache.put(c, types);
|
||||
}
|
||||
|
||||
try {
|
||||
DBusSignal s;
|
||||
Object[] args = Marshalling.deSerializeParameters(getParameters(), types, conn);
|
||||
if (null == args) s = (DBusSignal) con.newInstance(getPath());
|
||||
else {
|
||||
Object[] params = new Object[args.length + 1];
|
||||
params[0] = getPath();
|
||||
System.arraycopy(args, 0, params, 1, args.length);
|
||||
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Creating signal of type " + c + " with parameters " + Arrays.deepToString(params));
|
||||
s = (DBusSignal) con.newInstance(params);
|
||||
}
|
||||
s.headers = headers;
|
||||
s.wiredata = wiredata;
|
||||
s.bytecounter = wiredata.length;
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new signal.
|
||||
* This contructor MUST be called by all sub classes.
|
||||
*
|
||||
* @param objectpath The path to the object this is emitted from.
|
||||
* @param args The parameters of the signal.
|
||||
* @throws DBusException This is thrown if the subclass is incorrectly defined.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected DBusSignal(String objectpath, Object... args) throws DBusException {
|
||||
super(Message.Endian.BIG, Message.MessageType.SIGNAL, (byte) 0);
|
||||
|
||||
if (!objectpath.matches(AbstractConnection.OBJECT_REGEX))
|
||||
throw new DBusException(getString("invalidObjectPath") + objectpath);
|
||||
|
||||
Class<? extends DBusSignal> tc = getClass();
|
||||
String member;
|
||||
if (tc.isAnnotationPresent(DBusMemberName.class))
|
||||
member = tc.getAnnotation(DBusMemberName.class).value();
|
||||
else
|
||||
member = tc.getSimpleName();
|
||||
String iface = null;
|
||||
Class<? extends Object> enc = tc.getEnclosingClass();
|
||||
if (null == enc ||
|
||||
!DBusInterface.class.isAssignableFrom(enc) ||
|
||||
enc.getName().equals(enc.getSimpleName()))
|
||||
throw new DBusException(getString("signalsMustBeMemberOfClass"));
|
||||
else if (null != enc.getAnnotation(DBusInterfaceName.class))
|
||||
iface = enc.getAnnotation(DBusInterfaceName.class).value();
|
||||
else
|
||||
iface = AbstractConnection.dollar_pattern.matcher(enc.getName()).replaceAll(".");
|
||||
|
||||
headers.put(Message.HeaderField.PATH, objectpath);
|
||||
headers.put(Message.HeaderField.MEMBER, member);
|
||||
headers.put(Message.HeaderField.INTERFACE, iface);
|
||||
|
||||
Vector<Object> hargs = new Vector<Object>();
|
||||
hargs.add(new Object[]{Message.HeaderField.PATH, new Object[]{ArgumentType.OBJECT_PATH_STRING, objectpath}});
|
||||
hargs.add(new Object[]{Message.HeaderField.INTERFACE, new Object[]{ArgumentType.STRING_STRING, iface}});
|
||||
hargs.add(new Object[]{Message.HeaderField.MEMBER, new Object[]{ArgumentType.STRING_STRING, member}});
|
||||
|
||||
String sig = null;
|
||||
if (0 < args.length) {
|
||||
try {
|
||||
Type[] types = typeCache.get(tc);
|
||||
if (null == types) {
|
||||
Constructor<? extends DBusSignal> con = (Constructor<? extends DBusSignal>) tc.getDeclaredConstructors()[0];
|
||||
conCache.put(tc, con);
|
||||
Type[] ts = con.getGenericParameterTypes();
|
||||
types = new Type[ts.length - 1];
|
||||
for (int i = 1; i <= types.length; i++)
|
||||
if (ts[i] instanceof TypeVariable)
|
||||
types[i - 1] = ((TypeVariable<GenericDeclaration>) ts[i]).getBounds()[0];
|
||||
else
|
||||
types[i - 1] = ts[i];
|
||||
typeCache.put(tc, types);
|
||||
}
|
||||
sig = Marshalling.getDBusType(types);
|
||||
hargs.add(new Object[]{Message.HeaderField.SIGNATURE, new Object[]{ArgumentType.SIGNATURE_STRING, sig}});
|
||||
headers.put(Message.HeaderField.SIGNATURE, sig);
|
||||
setArgs(args);
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusException(getString("errorAddSignalParameters") + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
blen = new byte[4];
|
||||
appendBytes(blen);
|
||||
append("ua(yv)", ++serial, hargs.toArray());
|
||||
pad((byte) 8);
|
||||
}
|
||||
|
||||
void appendbody(AbstractConnection conn) throws DBusException {
|
||||
if (bodydone) return;
|
||||
|
||||
Type[] types = typeCache.get(getClass());
|
||||
Object[] args = Marshalling.convertParameters(getParameters(), types, conn);
|
||||
setArgs(args);
|
||||
String sig = getSig();
|
||||
|
||||
long c = bytecounter;
|
||||
if (null != args && 0 < args.length) append(sig, args);
|
||||
marshallint(bytecounter - c, blen, 0, 4);
|
||||
bodydone = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* Provides a long => MethodCall map which doesn't allocate objects
|
||||
* on insertion/removal. Keys must be inserted in ascending order.
|
||||
*/
|
||||
class EfficientMap {
|
||||
private long[] kv;
|
||||
private MethodCall[] vv;
|
||||
private int start;
|
||||
private int end;
|
||||
private int init_size;
|
||||
|
||||
public EfficientMap(int initial_size) {
|
||||
init_size = initial_size;
|
||||
shrink();
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
// create new vectors twice as long
|
||||
long[] oldkv = kv;
|
||||
kv = new long[oldkv.length * 2];
|
||||
MethodCall[] oldvv = vv;
|
||||
vv = new MethodCall[oldvv.length * 2];
|
||||
|
||||
// copy start->length to the start of the new vector
|
||||
System.arraycopy(oldkv, start, kv, 0, oldkv.length - start);
|
||||
System.arraycopy(oldvv, start, vv, 0, oldvv.length - start);
|
||||
// copy 0->end to the next part of the new vector
|
||||
if (end != (oldkv.length - 1)) {
|
||||
System.arraycopy(oldkv, 0, kv, oldkv.length - start, end + 1);
|
||||
System.arraycopy(oldvv, 0, vv, oldvv.length - start, end + 1);
|
||||
}
|
||||
// reposition pointers
|
||||
start = 0;
|
||||
end = oldkv.length;
|
||||
}
|
||||
|
||||
// create a new vector with just the valid keys in and return it
|
||||
public long[] getKeys() {
|
||||
int size;
|
||||
if (start < end) size = end - start;
|
||||
else size = kv.length - (start - end);
|
||||
long[] lv = new long[size];
|
||||
int copya;
|
||||
if (size > kv.length - start) copya = kv.length - start;
|
||||
else copya = size;
|
||||
System.arraycopy(kv, start, lv, 0, copya);
|
||||
if (copya < size) {
|
||||
System.arraycopy(kv, 0, lv, copya, size - copya);
|
||||
}
|
||||
return lv;
|
||||
}
|
||||
|
||||
private void shrink() {
|
||||
if (null != kv && kv.length == init_size) return;
|
||||
// reset to original size
|
||||
kv = new long[init_size];
|
||||
vv = new MethodCall[init_size];
|
||||
start = 0;
|
||||
end = 0;
|
||||
}
|
||||
|
||||
public void put(long l, MethodCall m) {
|
||||
// put this at the end
|
||||
kv[end] = l;
|
||||
vv[end] = m;
|
||||
// move the end
|
||||
if (end == (kv.length - 1)) end = 0;
|
||||
else end++;
|
||||
// if we are out of space, grow.
|
||||
if (end == start) grow();
|
||||
}
|
||||
|
||||
public MethodCall remove(long l) {
|
||||
// find the item
|
||||
int pos = find(l);
|
||||
// if we don't have it return null
|
||||
if (-1 == pos) return null;
|
||||
// get the value
|
||||
MethodCall m = vv[pos];
|
||||
// set it as unused
|
||||
vv[pos] = null;
|
||||
kv[pos] = -1;
|
||||
// move the pointer to the first full element
|
||||
while (-1 == kv[start]) {
|
||||
if (start == (kv.length - 1)) start = 0;
|
||||
else start++;
|
||||
// if we have emptied the list, shrink it
|
||||
if (start == end) {
|
||||
shrink();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public boolean contains(long l) {
|
||||
// check if find succeeds
|
||||
return -1 != find(l);
|
||||
}
|
||||
|
||||
/* could binary search, but it's probably the first one */
|
||||
private int find(long l) {
|
||||
int i = start;
|
||||
while (i != end && kv[i] != l)
|
||||
if (i == (kv.length - 1)) i = 0;
|
||||
else i++;
|
||||
if (i == end) return -1;
|
||||
return i;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
/**
|
||||
* Provides a Message queue which doesn't allocate objects
|
||||
* on insertion/removal.
|
||||
*/
|
||||
class EfficientQueue {
|
||||
private Message[] mv;
|
||||
private int start;
|
||||
private int end;
|
||||
private int init_size;
|
||||
|
||||
public EfficientQueue(int initial_size) {
|
||||
init_size = initial_size;
|
||||
shrink();
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Growing");
|
||||
// create new vectors twice as long
|
||||
Message[] oldmv = mv;
|
||||
mv = new Message[oldmv.length * 2];
|
||||
|
||||
// copy start->length to the start of the new vector
|
||||
System.arraycopy(oldmv, start, mv, 0, oldmv.length - start);
|
||||
// copy 0->end to the next part of the new vector
|
||||
if (end != (oldmv.length - 1)) {
|
||||
System.arraycopy(oldmv, 0, mv, oldmv.length - start, end + 1);
|
||||
}
|
||||
// reposition pointers
|
||||
start = 0;
|
||||
end = oldmv.length;
|
||||
}
|
||||
|
||||
// create a new vector with just the valid keys in and return it
|
||||
public Message[] getKeys() {
|
||||
if (start == end) return new Message[0];
|
||||
Message[] lv;
|
||||
if (start < end) {
|
||||
int size = end - start;
|
||||
lv = new Message[size];
|
||||
System.arraycopy(mv, start, lv, 0, size);
|
||||
} else {
|
||||
int size = mv.length - start + end;
|
||||
lv = new Message[size];
|
||||
System.arraycopy(mv, start, lv, 0, mv.length - start);
|
||||
System.arraycopy(mv, 0, lv, mv.length - start, end);
|
||||
}
|
||||
return lv;
|
||||
}
|
||||
|
||||
private void shrink() {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Shrinking");
|
||||
if (null != mv && mv.length == init_size) return;
|
||||
// reset to original size
|
||||
mv = new Message[init_size];
|
||||
start = 0;
|
||||
end = 0;
|
||||
}
|
||||
|
||||
public void add(Message m) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Enqueueing Message " + m);
|
||||
// put this at the end
|
||||
mv[end] = m;
|
||||
// move the end
|
||||
if (end == (mv.length - 1)) end = 0;
|
||||
else end++;
|
||||
// if we are out of space, grow.
|
||||
if (end == start) grow();
|
||||
}
|
||||
|
||||
public Message remove() {
|
||||
if (start == end) return null;
|
||||
// find the item
|
||||
int pos = start;
|
||||
// get the value
|
||||
Message m = mv[pos];
|
||||
// set it as unused
|
||||
mv[pos] = null;
|
||||
if (start == (mv.length - 1)) start = 0;
|
||||
else start++;
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Dequeueing " + m);
|
||||
return m;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
// check if find succeeds
|
||||
return start == end;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
if (end >= start)
|
||||
return end - start;
|
||||
else
|
||||
return mv.length - start + end;
|
||||
}
|
||||
}
|
144
federation/sssd/src/main/java/org/freedesktop/dbus/Error.java
Normal file
144
federation/sssd/src/main/java/org/freedesktop/dbus/Error.java
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
import org.freedesktop.dbus.exceptions.MessageFormatException;
|
||||
import org.freedesktop.dbus.exceptions.NotConnected;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Error messages which can be sent over the bus.
|
||||
*/
|
||||
public class Error extends Message {
|
||||
Error() {
|
||||
}
|
||||
|
||||
public Error(String dest, String errorName, long replyserial, String sig, Object... args) throws DBusException {
|
||||
this(null, dest, errorName, replyserial, sig, args);
|
||||
}
|
||||
|
||||
public Error(String source, String dest, String errorName, long replyserial, String sig, Object... args) throws DBusException {
|
||||
super(Message.Endian.BIG, Message.MessageType.ERROR, (byte) 0);
|
||||
|
||||
if (null == errorName)
|
||||
throw new MessageFormatException(getString("missingErrorName"));
|
||||
headers.put(Message.HeaderField.REPLY_SERIAL, replyserial);
|
||||
headers.put(Message.HeaderField.ERROR_NAME, errorName);
|
||||
|
||||
Vector<Object> hargs = new Vector<Object>();
|
||||
hargs.add(new Object[]{Message.HeaderField.ERROR_NAME, new Object[]{ArgumentType.STRING_STRING, errorName}});
|
||||
hargs.add(new Object[]{Message.HeaderField.REPLY_SERIAL, new Object[]{ArgumentType.UINT32_STRING, replyserial}});
|
||||
|
||||
if (null != source) {
|
||||
headers.put(Message.HeaderField.SENDER, source);
|
||||
hargs.add(new Object[]{Message.HeaderField.SENDER, new Object[]{ArgumentType.STRING_STRING, source}});
|
||||
}
|
||||
|
||||
if (null != dest) {
|
||||
headers.put(Message.HeaderField.DESTINATION, dest);
|
||||
hargs.add(new Object[]{Message.HeaderField.DESTINATION, new Object[]{ArgumentType.STRING_STRING, dest}});
|
||||
}
|
||||
|
||||
if (null != sig) {
|
||||
hargs.add(new Object[]{Message.HeaderField.SIGNATURE, new Object[]{ArgumentType.SIGNATURE_STRING, sig}});
|
||||
headers.put(Message.HeaderField.SIGNATURE, sig);
|
||||
setArgs(args);
|
||||
}
|
||||
|
||||
byte[] blen = new byte[4];
|
||||
appendBytes(blen);
|
||||
append("ua(yv)", serial, hargs.toArray());
|
||||
pad((byte) 8);
|
||||
|
||||
long c = bytecounter;
|
||||
if (null != sig) append(sig, args);
|
||||
marshallint(bytecounter - c, blen, 0, 4);
|
||||
}
|
||||
|
||||
public Error(String source, Message m, Throwable e) throws DBusException {
|
||||
this(source, m.getSource(), AbstractConnection.dollar_pattern.matcher(e.getClass().getName()).replaceAll("."), m.getSerial(), "s", e.getMessage());
|
||||
}
|
||||
|
||||
public Error(Message m, Throwable e) throws DBusException {
|
||||
this(m.getSource(), AbstractConnection.dollar_pattern.matcher(e.getClass().getName()).replaceAll("."), m.getSerial(), "s", e.getMessage());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Class<? extends DBusExecutionException> createExceptionClass(String name) {
|
||||
if (name == "org.freedesktop.DBus.Local.disconnected") return NotConnected.class;
|
||||
Class<? extends DBusExecutionException> c = null;
|
||||
do {
|
||||
try {
|
||||
c = (Class<? extends org.freedesktop.dbus.exceptions.DBusExecutionException>) Class.forName(name);
|
||||
} catch (ClassNotFoundException CNFe) {
|
||||
}
|
||||
name = name.replaceAll("\\.([^\\.]*)$", "\\$$1");
|
||||
} while (null == c && name.matches(".*\\..*"));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this into an exception of the correct type
|
||||
*/
|
||||
public DBusExecutionException getException() {
|
||||
try {
|
||||
Class<? extends DBusExecutionException> c = createExceptionClass(getName());
|
||||
if (null == c || !DBusExecutionException.class.isAssignableFrom(c)) c = DBusExecutionException.class;
|
||||
Constructor<? extends DBusExecutionException> con = c.getConstructor(String.class);
|
||||
DBusExecutionException ex;
|
||||
Object[] args = getParameters();
|
||||
if (null == args || 0 == args.length)
|
||||
ex = con.newInstance("");
|
||||
else {
|
||||
String s = "";
|
||||
for (Object o : args)
|
||||
s += o + " ";
|
||||
ex = con.newInstance(s.trim());
|
||||
}
|
||||
ex.setType(getName());
|
||||
return ex;
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug && null != e.getCause())
|
||||
Debug.print(Debug.ERR, e.getCause());
|
||||
DBusExecutionException ex;
|
||||
Object[] args = null;
|
||||
try {
|
||||
args = getParameters();
|
||||
} catch (Exception ee) {
|
||||
}
|
||||
if (null == args || 0 == args.length)
|
||||
ex = new DBusExecutionException("");
|
||||
else {
|
||||
String s = "";
|
||||
for (Object o : args)
|
||||
s += o + " ";
|
||||
ex = new DBusExecutionException(s.trim());
|
||||
}
|
||||
ex.setType(getName());
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw this as an exception of the correct type
|
||||
*/
|
||||
public void throwException() throws DBusExecutionException {
|
||||
throw getException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
class ExportedObject {
|
||||
@SuppressWarnings("unchecked")
|
||||
private String getAnnotations(AnnotatedElement c) {
|
||||
String ans = "";
|
||||
for (Annotation a : c.getDeclaredAnnotations()) {
|
||||
Class t = a.annotationType();
|
||||
String value = "";
|
||||
try {
|
||||
Method m = t.getMethod("value");
|
||||
value = m.invoke(a).toString();
|
||||
} catch (NoSuchMethodException NSMe) {
|
||||
} catch (InvocationTargetException ITe) {
|
||||
} catch (IllegalAccessException IAe) {
|
||||
}
|
||||
|
||||
ans += " <annotation name=\"" + AbstractConnection.dollar_pattern.matcher(t.getName()).replaceAll(".") + "\" value=\"" + value + "\" />\n";
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<MethodTuple, Method> getExportedMethods(Class c) throws DBusException {
|
||||
if (DBusInterface.class.equals(c)) return new HashMap<MethodTuple, Method>();
|
||||
Map<MethodTuple, Method> m = new HashMap<MethodTuple, Method>();
|
||||
for (Class i : c.getInterfaces())
|
||||
if (DBusInterface.class.equals(i)) {
|
||||
// add this class's public methods
|
||||
if (null != c.getAnnotation(DBusInterfaceName.class)) {
|
||||
String name = ((DBusInterfaceName) c.getAnnotation(DBusInterfaceName.class)).value();
|
||||
introspectiondata += " <interface name=\"" + name + "\">\n";
|
||||
DBusSignal.addInterfaceMap(c.getName(), name);
|
||||
} else {
|
||||
// don't let people export things which don't have a
|
||||
// valid D-Bus interface name
|
||||
if (c.getName().equals(c.getSimpleName()))
|
||||
throw new DBusException(getString("interfaceNotAllowedOutsidePackage"));
|
||||
if (c.getName().length() > DBusConnection.MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("introspectInterfaceExceedCharacters") + c.getName());
|
||||
else
|
||||
introspectiondata += " <interface name=\"" + AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".") + "\">\n";
|
||||
}
|
||||
introspectiondata += getAnnotations(c);
|
||||
for (Method meth : c.getDeclaredMethods())
|
||||
if (Modifier.isPublic(meth.getModifiers())) {
|
||||
String ms = "";
|
||||
String name;
|
||||
if (meth.isAnnotationPresent(DBusMemberName.class))
|
||||
name = meth.getAnnotation(DBusMemberName.class).value();
|
||||
else
|
||||
name = meth.getName();
|
||||
if (name.length() > DBusConnection.MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("introspectMethodExceedCharacters") + name);
|
||||
introspectiondata += " <method name=\"" + name + "\" >\n";
|
||||
introspectiondata += getAnnotations(meth);
|
||||
for (Class ex : meth.getExceptionTypes())
|
||||
if (DBusExecutionException.class.isAssignableFrom(ex))
|
||||
introspectiondata +=
|
||||
" <annotation name=\"org.freedesktop.DBus.Method.Error\" value=\"" + AbstractConnection.dollar_pattern.matcher(ex.getName()).replaceAll(".") + "\" />\n";
|
||||
for (Type pt : meth.getGenericParameterTypes())
|
||||
for (String s : Marshalling.getDBusType(pt)) {
|
||||
introspectiondata += " <arg type=\"" + s + "\" direction=\"in\"/>\n";
|
||||
ms += s;
|
||||
}
|
||||
if (!Void.TYPE.equals(meth.getGenericReturnType())) {
|
||||
if (Tuple.class.isAssignableFrom((Class) meth.getReturnType())) {
|
||||
ParameterizedType tc = (ParameterizedType) meth.getGenericReturnType();
|
||||
Type[] ts = tc.getActualTypeArguments();
|
||||
|
||||
for (Type t : ts)
|
||||
if (t != null)
|
||||
for (String s : Marshalling.getDBusType(t))
|
||||
introspectiondata += " <arg type=\"" + s + "\" direction=\"out\"/>\n";
|
||||
} else if (Object[].class.equals(meth.getGenericReturnType())) {
|
||||
throw new DBusException(getString("cannotIntrospectReturnType"));
|
||||
} else
|
||||
for (String s : Marshalling.getDBusType(meth.getGenericReturnType()))
|
||||
introspectiondata += " <arg type=\"" + s + "\" direction=\"out\"/>\n";
|
||||
}
|
||||
introspectiondata += " </method>\n";
|
||||
m.put(new MethodTuple(name, ms), meth);
|
||||
}
|
||||
for (Class sig : c.getDeclaredClasses())
|
||||
if (DBusSignal.class.isAssignableFrom(sig)) {
|
||||
String name;
|
||||
if (sig.isAnnotationPresent(DBusMemberName.class)) {
|
||||
name = ((DBusMemberName) sig.getAnnotation(DBusMemberName.class)).value();
|
||||
DBusSignal.addSignalMap(sig.getSimpleName(), name);
|
||||
} else
|
||||
name = sig.getSimpleName();
|
||||
if (name.length() > DBusConnection.MAX_NAME_LENGTH)
|
||||
throw new DBusException(getString("introspectSignalExceedCharacters") + name);
|
||||
introspectiondata += " <signal name=\"" + name + "\">\n";
|
||||
Constructor con = sig.getConstructors()[0];
|
||||
Type[] ts = con.getGenericParameterTypes();
|
||||
for (int j = 1; j < ts.length; j++)
|
||||
for (String s : Marshalling.getDBusType(ts[j]))
|
||||
introspectiondata += " <arg type=\"" + s + "\" direction=\"out\" />\n";
|
||||
introspectiondata += getAnnotations(sig);
|
||||
introspectiondata += " </signal>\n";
|
||||
|
||||
}
|
||||
introspectiondata += " </interface>\n";
|
||||
} else {
|
||||
// recurse
|
||||
m.putAll(getExportedMethods(i));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Map<MethodTuple, Method> methods;
|
||||
Reference<DBusInterface> object;
|
||||
String introspectiondata;
|
||||
|
||||
public ExportedObject(DBusInterface object, boolean weakreferences) throws DBusException {
|
||||
if (weakreferences)
|
||||
this.object = new WeakReference<DBusInterface>(object);
|
||||
else
|
||||
this.object = new StrongReference<DBusInterface>(object);
|
||||
introspectiondata = "";
|
||||
methods = getExportedMethods(object.getClass());
|
||||
introspectiondata +=
|
||||
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" +
|
||||
" <method name=\"Introspect\">\n" +
|
||||
" <arg type=\"s\" direction=\"out\"/>\n" +
|
||||
" </method>\n" +
|
||||
" </interface>\n";
|
||||
introspectiondata +=
|
||||
" <interface name=\"org.freedesktop.DBus.Peer\">\n" +
|
||||
" <method name=\"Ping\">\n" +
|
||||
" </method>\n" +
|
||||
" </interface>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Pescetti Pseudo-Duplimate Generator
|
||||
*
|
||||
* Copyright (C) 2007 Matthew Johnson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License Version 2 as published by
|
||||
* the Free Software Foundation. This program is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details. You should have received a
|
||||
* copy of the GNU Lesser General Public License along with this program; if not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* To Contact me, please email src@matthew.ath.cx
|
||||
*
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class Gettext {
|
||||
private static ResourceBundle myResources =
|
||||
ResourceBundle.getBundle("en_US");
|
||||
|
||||
public static String getString(String s) {
|
||||
return myResources.getString(s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
|
||||
class InternalSignal extends DBusSignal {
|
||||
public InternalSignal(String source, String objectpath, String name, String iface, String sig, long serial, Object... parameters) throws DBusException {
|
||||
super(objectpath, iface, name, sig, parameters);
|
||||
this.serial = serial;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,629 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.types.DBusListType;
|
||||
import org.freedesktop.dbus.types.DBusMapType;
|
||||
import org.freedesktop.dbus.types.DBusStructType;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Contains static methods for marshalling values.
|
||||
*/
|
||||
public class Marshalling {
|
||||
private static Map<Type, String[]> typeCache = new HashMap<Type, String[]>();
|
||||
|
||||
/**
|
||||
* Will return the DBus type corresponding to the given Java type.
|
||||
* Note, container type should have their ParameterizedType not their
|
||||
* Class passed in here.
|
||||
*
|
||||
* @param c The Java types.
|
||||
* @return The DBus types.
|
||||
* @throws DBusException If the given type cannot be converted to a DBus type.
|
||||
*/
|
||||
public static String getDBusType(Type[] c) throws DBusException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Type t : c)
|
||||
for (String s : getDBusType(t))
|
||||
sb.append(s);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the DBus type corresponding to the given Java type.
|
||||
* Note, container type should have their ParameterizedType not their
|
||||
* Class passed in here.
|
||||
*
|
||||
* @param c The Java type.
|
||||
* @return The DBus type.
|
||||
* @throws DBusException If the given type cannot be converted to a DBus type.
|
||||
*/
|
||||
public static String[] getDBusType(Type c) throws DBusException {
|
||||
String[] cached = typeCache.get(c);
|
||||
if (null != cached) return cached;
|
||||
cached = getDBusType(c, false);
|
||||
typeCache.put(c, cached);
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the DBus type corresponding to the given Java type.
|
||||
* Note, container type should have their ParameterizedType not their
|
||||
* Class passed in here.
|
||||
*
|
||||
* @param c The Java type.
|
||||
* @param basic If true enforces this to be a non-compound type. (compound types are Maps, Structs and Lists/arrays).
|
||||
* @return The DBus type.
|
||||
* @throws DBusException If the given type cannot be converted to a DBus type.
|
||||
*/
|
||||
public static String[] getDBusType(Type c, boolean basic) throws DBusException {
|
||||
return recursiveGetDBusType(c, basic, 0);
|
||||
}
|
||||
|
||||
private static StringBuffer[] out = new StringBuffer[10];
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String[] recursiveGetDBusType(Type c, boolean basic, int level) throws DBusException {
|
||||
if (out.length <= level) {
|
||||
StringBuffer[] newout = new StringBuffer[out.length];
|
||||
System.arraycopy(out, 0, newout, 0, out.length);
|
||||
out = newout;
|
||||
}
|
||||
if (null == out[level]) out[level] = new StringBuffer();
|
||||
else out[level].delete(0, out[level].length());
|
||||
|
||||
if (basic && !(c instanceof Class))
|
||||
throw new DBusException(c + getString("notBasicType"));
|
||||
|
||||
if (c instanceof TypeVariable) out[level].append((char) Message.ArgumentType.VARIANT);
|
||||
else if (c instanceof GenericArrayType) {
|
||||
out[level].append((char) Message.ArgumentType.ARRAY);
|
||||
String[] s = recursiveGetDBusType(((GenericArrayType) c).getGenericComponentType(), false, level + 1);
|
||||
if (s.length != 1) throw new DBusException(getString("multiValuedArrayNotPermitted"));
|
||||
out[level].append(s[0]);
|
||||
} else if ((c instanceof Class &&
|
||||
DBusSerializable.class.isAssignableFrom((Class<? extends Object>) c)) ||
|
||||
(c instanceof ParameterizedType &&
|
||||
DBusSerializable.class.isAssignableFrom((Class<? extends Object>) ((ParameterizedType) c).getRawType()))) {
|
||||
// it's a custom serializable type
|
||||
Type[] newtypes = null;
|
||||
if (c instanceof Class) {
|
||||
for (Method m : ((Class<? extends Object>) c).getDeclaredMethods())
|
||||
if (m.getName().equals("deserialize"))
|
||||
newtypes = m.getGenericParameterTypes();
|
||||
} else
|
||||
for (Method m : ((Class<? extends Object>) ((ParameterizedType) c).getRawType()).getDeclaredMethods())
|
||||
if (m.getName().equals("deserialize"))
|
||||
newtypes = m.getGenericParameterTypes();
|
||||
|
||||
if (null == newtypes) throw new DBusException(getString("mustImplementDeserializeMethod"));
|
||||
|
||||
String[] sigs = new String[newtypes.length];
|
||||
for (int j = 0; j < sigs.length; j++) {
|
||||
String[] ss = recursiveGetDBusType(newtypes[j], false, level + 1);
|
||||
if (1 != ss.length) throw new DBusException(getString("mustSerializeNativeDBusTypes"));
|
||||
sigs[j] = ss[0];
|
||||
}
|
||||
return sigs;
|
||||
} else if (c instanceof ParameterizedType) {
|
||||
ParameterizedType p = (ParameterizedType) c;
|
||||
if (p.getRawType().equals(Map.class)) {
|
||||
out[level].append("a{");
|
||||
Type[] t = p.getActualTypeArguments();
|
||||
try {
|
||||
String[] s = recursiveGetDBusType(t[0], true, level + 1);
|
||||
if (s.length != 1) throw new DBusException(getString("multiValuedArrayNotPermitted"));
|
||||
out[level].append(s[0]);
|
||||
s = recursiveGetDBusType(t[1], false, level + 1);
|
||||
if (s.length != 1) throw new DBusException(getString("multiValuedArrayNotPermitted"));
|
||||
out[level].append(s[0]);
|
||||
} catch (ArrayIndexOutOfBoundsException AIOOBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
|
||||
throw new DBusException(getString("mapParameters"));
|
||||
}
|
||||
out[level].append('}');
|
||||
} else if (List.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) {
|
||||
for (Type t : p.getActualTypeArguments()) {
|
||||
if (Type.class.equals(t))
|
||||
out[level].append((char) Message.ArgumentType.SIGNATURE);
|
||||
else {
|
||||
String[] s = recursiveGetDBusType(t, false, level + 1);
|
||||
if (s.length != 1) throw new DBusException(getString("multiValuedArrayNotPermitted"));
|
||||
out[level].append((char) Message.ArgumentType.ARRAY);
|
||||
out[level].append(s[0]);
|
||||
}
|
||||
}
|
||||
} else if (p.getRawType().equals(Variant.class)) {
|
||||
out[level].append((char) Message.ArgumentType.VARIANT);
|
||||
} else if (DBusInterface.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) {
|
||||
out[level].append((char) Message.ArgumentType.OBJECT_PATH);
|
||||
} else if (Tuple.class.isAssignableFrom((Class<? extends Object>) p.getRawType())) {
|
||||
Type[] ts = p.getActualTypeArguments();
|
||||
Vector<String> vs = new Vector<String>();
|
||||
for (Type t : ts)
|
||||
for (String s : recursiveGetDBusType(t, false, level + 1))
|
||||
vs.add(s);
|
||||
return vs.toArray(new String[0]);
|
||||
} else
|
||||
throw new DBusException(getString("nonExportableParameterizedType") + c);
|
||||
} else if (c.equals(Byte.class)) out[level].append((char) Message.ArgumentType.BYTE);
|
||||
else if (c.equals(Byte.TYPE)) out[level].append((char) Message.ArgumentType.BYTE);
|
||||
else if (c.equals(Boolean.class)) out[level].append((char) Message.ArgumentType.BOOLEAN);
|
||||
else if (c.equals(Boolean.TYPE)) out[level].append((char) Message.ArgumentType.BOOLEAN);
|
||||
else if (c.equals(Short.class)) out[level].append((char) Message.ArgumentType.INT16);
|
||||
else if (c.equals(Short.TYPE)) out[level].append((char) Message.ArgumentType.INT16);
|
||||
else if (c.equals(UInt16.class)) out[level].append((char) Message.ArgumentType.UINT16);
|
||||
else if (c.equals(Integer.class)) out[level].append((char) Message.ArgumentType.INT32);
|
||||
else if (c.equals(Integer.TYPE)) out[level].append((char) Message.ArgumentType.INT32);
|
||||
else if (c.equals(UInt32.class)) out[level].append((char) Message.ArgumentType.UINT32);
|
||||
else if (c.equals(Long.class)) out[level].append((char) Message.ArgumentType.INT64);
|
||||
else if (c.equals(Long.TYPE)) out[level].append((char) Message.ArgumentType.INT64);
|
||||
else if (c.equals(UInt64.class)) out[level].append((char) Message.ArgumentType.UINT64);
|
||||
else if (c.equals(Double.class)) out[level].append((char) Message.ArgumentType.DOUBLE);
|
||||
else if (c.equals(Double.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE);
|
||||
else if (c.equals(Float.class) && AbstractConnection.FLOAT_SUPPORT)
|
||||
out[level].append((char) Message.ArgumentType.FLOAT);
|
||||
else if (c.equals(Float.class)) out[level].append((char) Message.ArgumentType.DOUBLE);
|
||||
else if (c.equals(Float.TYPE) && AbstractConnection.FLOAT_SUPPORT)
|
||||
out[level].append((char) Message.ArgumentType.FLOAT);
|
||||
else if (c.equals(Float.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE);
|
||||
else if (c.equals(String.class)) out[level].append((char) Message.ArgumentType.STRING);
|
||||
else if (c.equals(Variant.class)) out[level].append((char) Message.ArgumentType.VARIANT);
|
||||
else if (c instanceof Class &&
|
||||
DBusInterface.class.isAssignableFrom((Class<? extends Object>) c))
|
||||
out[level].append((char) Message.ArgumentType.OBJECT_PATH);
|
||||
else if (c instanceof Class &&
|
||||
Path.class.equals((Class<? extends Object>) c))
|
||||
out[level].append((char) Message.ArgumentType.OBJECT_PATH);
|
||||
else if (c instanceof Class &&
|
||||
ObjectPath.class.equals((Class<? extends Object>) c))
|
||||
out[level].append((char) Message.ArgumentType.OBJECT_PATH);
|
||||
else if (c instanceof Class &&
|
||||
((Class<? extends Object>) c).isArray()) {
|
||||
if (Type.class.equals(((Class<? extends Object>) c).getComponentType()))
|
||||
out[level].append((char) Message.ArgumentType.SIGNATURE);
|
||||
else {
|
||||
out[level].append((char) Message.ArgumentType.ARRAY);
|
||||
String[] s = recursiveGetDBusType(((Class<? extends Object>) c).getComponentType(), false, level + 1);
|
||||
if (s.length != 1) throw new DBusException(getString("multiValuedArrayNotPermitted"));
|
||||
out[level].append(s[0]);
|
||||
}
|
||||
} else if (c instanceof Class &&
|
||||
Struct.class.isAssignableFrom((Class<? extends Object>) c)) {
|
||||
out[level].append((char) Message.ArgumentType.STRUCT1);
|
||||
Type[] ts = Container.getTypeCache(c);
|
||||
if (null == ts) {
|
||||
Field[] fs = ((Class<? extends Object>) c).getDeclaredFields();
|
||||
ts = new Type[fs.length];
|
||||
for (Field f : fs) {
|
||||
Position p = f.getAnnotation(Position.class);
|
||||
if (null == p) continue;
|
||||
ts[p.value()] = f.getGenericType();
|
||||
}
|
||||
Container.putTypeCache(c, ts);
|
||||
}
|
||||
|
||||
for (Type t : ts)
|
||||
if (t != null)
|
||||
for (String s : recursiveGetDBusType(t, false, level + 1))
|
||||
out[level].append(s);
|
||||
out[level].append(')');
|
||||
} else {
|
||||
throw new DBusException(getString("nonExportableType") + c);
|
||||
}
|
||||
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Converted Java type: " + c + " to D-Bus Type: " + out[level]);
|
||||
|
||||
return new String[]{out[level].toString()};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a dbus type string into Java Type objects,
|
||||
*
|
||||
* @param dbus The DBus type or types.
|
||||
* @param rv Vector to return the types in.
|
||||
* @param limit Maximum number of types to parse (-1 == nolimit).
|
||||
* @return number of characters parsed from the type string.
|
||||
*/
|
||||
public static int getJavaType(String dbus, List<Type> rv, int limit) throws DBusException {
|
||||
if (null == dbus || "".equals(dbus) || 0 == limit) return 0;
|
||||
|
||||
try {
|
||||
int i = 0;
|
||||
for (; i < dbus.length() && (-1 == limit || limit > rv.size()); i++)
|
||||
switch (dbus.charAt(i)) {
|
||||
case Message.ArgumentType.STRUCT1:
|
||||
int j = i + 1;
|
||||
for (int c = 1; c > 0; j++) {
|
||||
if (')' == dbus.charAt(j)) c--;
|
||||
else if (Message.ArgumentType.STRUCT1 == dbus.charAt(j)) c++;
|
||||
}
|
||||
|
||||
Vector<Type> contained = new Vector<Type>();
|
||||
int c = getJavaType(dbus.substring(i + 1, j - 1), contained, -1);
|
||||
rv.add(new DBusStructType(contained.toArray(new Type[0])));
|
||||
i = j;
|
||||
break;
|
||||
case Message.ArgumentType.ARRAY:
|
||||
if (Message.ArgumentType.DICT_ENTRY1 == dbus.charAt(i + 1)) {
|
||||
contained = new Vector<Type>();
|
||||
c = getJavaType(dbus.substring(i + 2), contained, 2);
|
||||
rv.add(new DBusMapType(contained.get(0), contained.get(1)));
|
||||
i += (c + 2);
|
||||
} else {
|
||||
contained = new Vector<Type>();
|
||||
c = getJavaType(dbus.substring(i + 1), contained, 1);
|
||||
rv.add(new DBusListType(contained.get(0)));
|
||||
i += c;
|
||||
}
|
||||
break;
|
||||
case Message.ArgumentType.VARIANT:
|
||||
rv.add(Variant.class);
|
||||
break;
|
||||
case Message.ArgumentType.BOOLEAN:
|
||||
rv.add(Boolean.class);
|
||||
break;
|
||||
case Message.ArgumentType.INT16:
|
||||
rv.add(Short.class);
|
||||
break;
|
||||
case Message.ArgumentType.BYTE:
|
||||
rv.add(Byte.class);
|
||||
break;
|
||||
case Message.ArgumentType.OBJECT_PATH:
|
||||
rv.add(DBusInterface.class);
|
||||
break;
|
||||
case Message.ArgumentType.UINT16:
|
||||
rv.add(UInt16.class);
|
||||
break;
|
||||
case Message.ArgumentType.INT32:
|
||||
rv.add(Integer.class);
|
||||
break;
|
||||
case Message.ArgumentType.UINT32:
|
||||
rv.add(UInt32.class);
|
||||
break;
|
||||
case Message.ArgumentType.INT64:
|
||||
rv.add(Long.class);
|
||||
break;
|
||||
case Message.ArgumentType.UINT64:
|
||||
rv.add(UInt64.class);
|
||||
break;
|
||||
case Message.ArgumentType.DOUBLE:
|
||||
rv.add(Double.class);
|
||||
break;
|
||||
case Message.ArgumentType.FLOAT:
|
||||
rv.add(Float.class);
|
||||
break;
|
||||
case Message.ArgumentType.STRING:
|
||||
rv.add(String.class);
|
||||
break;
|
||||
case Message.ArgumentType.SIGNATURE:
|
||||
rv.add(Type[].class);
|
||||
break;
|
||||
case Message.ArgumentType.DICT_ENTRY1:
|
||||
rv.add(Map.Entry.class);
|
||||
contained = new Vector<Type>();
|
||||
c = getJavaType(dbus.substring(i + 1), contained, 2);
|
||||
i += c + 1;
|
||||
break;
|
||||
default:
|
||||
throw new DBusException(MessageFormat.format(getString("parseDBusSignatureFailure"), new Object[]{dbus, dbus.charAt(i)}));
|
||||
}
|
||||
return i;
|
||||
} catch (IndexOutOfBoundsException IOOBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOOBe);
|
||||
throw new DBusException(getString("parseDBusTypeSignatureFailure") + dbus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively converts types for serialization onto DBus.
|
||||
*
|
||||
* @param parameters The parameters to convert.
|
||||
* @param types The (possibly generic) types of the parameters.
|
||||
* @return The converted parameters.
|
||||
* @throws DBusException Thrown if there is an error in converting the objects.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object[] convertParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws DBusException {
|
||||
if (null == parameters) return null;
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "Converting " + i + " from " + parameters[i] + " to " + types[i]);
|
||||
if (null == parameters[i]) continue;
|
||||
|
||||
if (parameters[i] instanceof DBusSerializable) {
|
||||
for (Method m : parameters[i].getClass().getDeclaredMethods())
|
||||
if (m.getName().equals("deserialize")) {
|
||||
Type[] newtypes = m.getParameterTypes();
|
||||
Type[] expand = new Type[types.length + newtypes.length - 1];
|
||||
System.arraycopy(types, 0, expand, 0, i);
|
||||
System.arraycopy(newtypes, 0, expand, i, newtypes.length);
|
||||
System.arraycopy(types, i + 1, expand, i + newtypes.length, types.length - i - 1);
|
||||
types = expand;
|
||||
Object[] newparams = ((DBusSerializable) parameters[i]).serialize();
|
||||
Object[] exparams = new Object[parameters.length + newparams.length - 1];
|
||||
System.arraycopy(parameters, 0, exparams, 0, i);
|
||||
System.arraycopy(newparams, 0, exparams, i, newparams.length);
|
||||
System.arraycopy(parameters, i + 1, exparams, i + newparams.length, parameters.length - i - 1);
|
||||
parameters = exparams;
|
||||
}
|
||||
i--;
|
||||
} else if (parameters[i] instanceof Tuple) {
|
||||
Type[] newtypes = ((ParameterizedType) types[i]).getActualTypeArguments();
|
||||
Type[] expand = new Type[types.length + newtypes.length - 1];
|
||||
System.arraycopy(types, 0, expand, 0, i);
|
||||
System.arraycopy(newtypes, 0, expand, i, newtypes.length);
|
||||
System.arraycopy(types, i + 1, expand, i + newtypes.length, types.length - i - 1);
|
||||
types = expand;
|
||||
Object[] newparams = ((Tuple) parameters[i]).getParameters();
|
||||
Object[] exparams = new Object[parameters.length + newparams.length - 1];
|
||||
System.arraycopy(parameters, 0, exparams, 0, i);
|
||||
System.arraycopy(newparams, 0, exparams, i, newparams.length);
|
||||
System.arraycopy(parameters, i + 1, exparams, i + newparams.length, parameters.length - i - 1);
|
||||
parameters = exparams;
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "New params: " + Arrays.deepToString(parameters) + " new types: " + Arrays.deepToString(types));
|
||||
i--;
|
||||
} else if (types[i] instanceof TypeVariable &&
|
||||
!(parameters[i] instanceof Variant))
|
||||
// its an unwrapped variant, wrap it
|
||||
parameters[i] = new Variant<Object>(parameters[i]);
|
||||
else if (parameters[i] instanceof DBusInterface)
|
||||
parameters[i] = conn.getExportedObject((DBusInterface) parameters[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Object deSerializeParameter(Object parameter, Type type, AbstractConnection conn) throws Exception {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "Deserializing from " + parameter.getClass() + " to " + type.getClass());
|
||||
if (null == parameter)
|
||||
return null;
|
||||
|
||||
// its a wrapped variant, unwrap it
|
||||
if (type instanceof TypeVariable
|
||||
&& parameter instanceof Variant) {
|
||||
parameter = ((Variant) parameter).getValue();
|
||||
}
|
||||
|
||||
// Turn a signature into a Type[]
|
||||
if (type instanceof Class
|
||||
&& ((Class) type).isArray()
|
||||
&& ((Class) type).getComponentType().equals(Type.class)
|
||||
&& parameter instanceof String) {
|
||||
Vector<Type> rv = new Vector<Type>();
|
||||
getJavaType((String) parameter, rv, -1);
|
||||
parameter = rv.toArray(new Type[0]);
|
||||
}
|
||||
|
||||
// its an object path, get/create the proxy
|
||||
if (parameter instanceof ObjectPath) {
|
||||
if (type instanceof Class && DBusInterface.class.isAssignableFrom((Class) type))
|
||||
parameter = conn.getExportedObject(
|
||||
((ObjectPath) parameter).source,
|
||||
((ObjectPath) parameter).path);
|
||||
else
|
||||
parameter = new Path(((ObjectPath) parameter).path);
|
||||
}
|
||||
|
||||
// it should be a struct. create it
|
||||
if (parameter instanceof Object[] &&
|
||||
type instanceof Class &&
|
||||
Struct.class.isAssignableFrom((Class) type)) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Creating Struct " + type + " from " + parameter);
|
||||
Type[] ts = Container.getTypeCache(type);
|
||||
if (null == ts) {
|
||||
Field[] fs = ((Class) type).getDeclaredFields();
|
||||
ts = new Type[fs.length];
|
||||
for (Field f : fs) {
|
||||
Position p = f.getAnnotation(Position.class);
|
||||
if (null == p) continue;
|
||||
ts[p.value()] = f.getGenericType();
|
||||
}
|
||||
Container.putTypeCache(type, ts);
|
||||
}
|
||||
|
||||
// recurse over struct contents
|
||||
parameter = deSerializeParameters((Object[]) parameter, ts, conn);
|
||||
for (Constructor con : ((Class) type).getDeclaredConstructors()) {
|
||||
try {
|
||||
parameter = con.newInstance((Object[]) parameter);
|
||||
break;
|
||||
} catch (IllegalArgumentException IAe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recurse over arrays
|
||||
if (parameter instanceof Object[]) {
|
||||
Type[] ts = new Type[((Object[]) parameter).length];
|
||||
Arrays.fill(ts, parameter.getClass().getComponentType());
|
||||
parameter = deSerializeParameters((Object[]) parameter,
|
||||
ts, conn);
|
||||
}
|
||||
if (parameter instanceof List) {
|
||||
Type type2;
|
||||
if (type instanceof ParameterizedType)
|
||||
type2 = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
else if (type instanceof GenericArrayType)
|
||||
type2 = ((GenericArrayType) type).getGenericComponentType();
|
||||
else if (type instanceof Class && ((Class) type).isArray())
|
||||
type2 = ((Class) type).getComponentType();
|
||||
else
|
||||
type2 = null;
|
||||
if (null != type2)
|
||||
parameter = deSerializeParameters((List) parameter, type2, conn);
|
||||
}
|
||||
|
||||
// correct floats if appropriate
|
||||
if (type.equals(Float.class) || type.equals(Float.TYPE))
|
||||
if (!(parameter instanceof Float))
|
||||
parameter = ((Number) parameter).floatValue();
|
||||
|
||||
// make sure arrays are in the correct format
|
||||
if (parameter instanceof Object[] ||
|
||||
parameter instanceof List ||
|
||||
parameter.getClass().isArray()) {
|
||||
if (type instanceof ParameterizedType)
|
||||
parameter = ArrayFrob.convert(parameter,
|
||||
(Class<? extends Object>) ((ParameterizedType) type).getRawType());
|
||||
else if (type instanceof GenericArrayType) {
|
||||
Type ct = ((GenericArrayType) type).getGenericComponentType();
|
||||
Class cc = null;
|
||||
if (ct instanceof Class)
|
||||
cc = (Class) ct;
|
||||
if (ct instanceof ParameterizedType)
|
||||
cc = (Class) ((ParameterizedType) ct).getRawType();
|
||||
Object o = Array.newInstance(cc, 0);
|
||||
parameter = ArrayFrob.convert(parameter,
|
||||
o.getClass());
|
||||
} else if (type instanceof Class &&
|
||||
((Class) type).isArray()) {
|
||||
Class cc = ((Class) type).getComponentType();
|
||||
if ((cc.equals(Float.class) || cc.equals(Float.TYPE))
|
||||
&& (parameter instanceof double[])) {
|
||||
double[] tmp1 = (double[]) parameter;
|
||||
float[] tmp2 = new float[tmp1.length];
|
||||
for (int i = 0; i < tmp1.length; i++)
|
||||
tmp2[i] = (float) tmp1[i];
|
||||
parameter = tmp2;
|
||||
}
|
||||
Object o = Array.newInstance(cc, 0);
|
||||
parameter = ArrayFrob.convert(parameter,
|
||||
o.getClass());
|
||||
}
|
||||
}
|
||||
if (parameter instanceof DBusMap) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing a Map");
|
||||
DBusMap dmap = (DBusMap) parameter;
|
||||
Type[] maptypes = ((ParameterizedType) type).getActualTypeArguments();
|
||||
for (int i = 0; i < dmap.entries.length; i++) {
|
||||
dmap.entries[i][0] = deSerializeParameter(dmap.entries[i][0], maptypes[0], conn);
|
||||
dmap.entries[i][1] = deSerializeParameter(dmap.entries[i][1], maptypes[1], conn);
|
||||
}
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
static List<Object> deSerializeParameters(List<Object> parameters, Type type, AbstractConnection conn) throws Exception {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserializing from " + parameters + " to " + type);
|
||||
if (null == parameters) return null;
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
if (null == parameters.get(i)) continue;
|
||||
|
||||
/* DO NOT DO THIS! IT'S REALLY NOT SUPPORTED!
|
||||
* if (type instanceof Class &&
|
||||
DBusSerializable.class.isAssignableFrom((Class) types[i])) {
|
||||
for (Method m: ((Class) types[i]).getDeclaredMethods())
|
||||
if (m.getName().equals("deserialize")) {
|
||||
Type[] newtypes = m.getGenericParameterTypes();
|
||||
try {
|
||||
Object[] sub = new Object[newtypes.length];
|
||||
System.arraycopy(parameters, i, sub, 0, newtypes.length);
|
||||
sub = deSerializeParameters(sub, newtypes, conn);
|
||||
DBusSerializable sz = (DBusSerializable) ((Class) types[i]).newInstance();
|
||||
m.invoke(sz, sub);
|
||||
Object[] compress = new Object[parameters.length - newtypes.length + 1];
|
||||
System.arraycopy(parameters, 0, compress, 0, i);
|
||||
compress[i] = sz;
|
||||
System.arraycopy(parameters, i + newtypes.length, compress, i+1, parameters.length - i - newtypes.length);
|
||||
parameters = compress;
|
||||
} catch (ArrayIndexOutOfBoundsException AIOOBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
|
||||
throw new DBusException("Not enough elements to create custom object from serialized data ("+(parameters.size()-i)+" < "+(newtypes.length)+")");
|
||||
}
|
||||
}
|
||||
} else*/
|
||||
parameters.set(i, deSerializeParameter(parameters.get(i), type, conn));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Object[] deSerializeParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws Exception {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "Deserializing from " + Arrays.deepToString(parameters) + " to " + Arrays.deepToString(types));
|
||||
if (null == parameters) return null;
|
||||
|
||||
if (types.length == 1 && types[0] instanceof ParameterizedType
|
||||
&& Tuple.class.isAssignableFrom((Class) ((ParameterizedType) types[0]).getRawType())) {
|
||||
types = ((ParameterizedType) types[0]).getActualTypeArguments();
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
// CHECK IF ARRAYS HAVE THE SAME LENGTH <-- has to happen after expanding parameters
|
||||
if (i >= types.length) {
|
||||
if (Debug.debug) {
|
||||
for (int j = 0; j < parameters.length; j++) {
|
||||
Debug.print(Debug.ERR, String.format("Error, Parameters difference (%1d, '%2s')", j, parameters[j].toString()));
|
||||
}
|
||||
}
|
||||
throw new DBusException(getString("errorDeserializingMessage"));
|
||||
}
|
||||
if (null == parameters[i]) continue;
|
||||
|
||||
if ((types[i] instanceof Class &&
|
||||
DBusSerializable.class.isAssignableFrom((Class<? extends Object>) types[i])) ||
|
||||
(types[i] instanceof ParameterizedType &&
|
||||
DBusSerializable.class.isAssignableFrom((Class<? extends Object>) ((ParameterizedType) types[i]).getRawType()))) {
|
||||
Class<? extends DBusSerializable> dsc;
|
||||
if (types[i] instanceof Class)
|
||||
dsc = (Class<? extends DBusSerializable>) types[i];
|
||||
else
|
||||
dsc = (Class<? extends DBusSerializable>) ((ParameterizedType) types[i]).getRawType();
|
||||
for (Method m : dsc.getDeclaredMethods())
|
||||
if (m.getName().equals("deserialize")) {
|
||||
Type[] newtypes = m.getGenericParameterTypes();
|
||||
try {
|
||||
Object[] sub = new Object[newtypes.length];
|
||||
System.arraycopy(parameters, i, sub, 0, newtypes.length);
|
||||
sub = deSerializeParameters(sub, newtypes, conn);
|
||||
DBusSerializable sz = dsc.newInstance();
|
||||
m.invoke(sz, sub);
|
||||
Object[] compress = new Object[parameters.length - newtypes.length + 1];
|
||||
System.arraycopy(parameters, 0, compress, 0, i);
|
||||
compress[i] = sz;
|
||||
System.arraycopy(parameters, i + newtypes.length, compress, i + 1, parameters.length - i - newtypes.length);
|
||||
parameters = compress;
|
||||
} catch (ArrayIndexOutOfBoundsException AIOOBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
|
||||
throw new DBusException(MessageFormat.format(getString("notEnoughElementsToCreateCustomObject"),
|
||||
new Object[]{parameters.length - i, newtypes.length}));
|
||||
}
|
||||
}
|
||||
} else
|
||||
parameters[i] = deSerializeParameter(parameters[i], types[i], conn);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
1216
federation/sssd/src/main/java/org/freedesktop/dbus/Message.java
Normal file
1216
federation/sssd/src/main/java/org/freedesktop/dbus/Message.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import cx.ath.matthew.utils.Hexdump;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.MessageProtocolVersionException;
|
||||
import org.freedesktop.dbus.exceptions.MessageTypeException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class MessageReader {
|
||||
private InputStream in;
|
||||
private byte[] buf = null;
|
||||
private byte[] tbuf = null;
|
||||
private byte[] header = null;
|
||||
private byte[] body = null;
|
||||
private int[] len = new int[4];
|
||||
|
||||
public MessageReader(InputStream in) {
|
||||
this.in = new BufferedInputStream(in);
|
||||
}
|
||||
|
||||
public Message readMessage() throws IOException, DBusException {
|
||||
int rv;
|
||||
/* Read the 12 byte fixed header, retrying as neccessary */
|
||||
if (null == buf) {
|
||||
buf = new byte[12];
|
||||
len[0] = 0;
|
||||
}
|
||||
if (len[0] < 12) {
|
||||
try {
|
||||
rv = in.read(buf, len[0], 12 - len[0]);
|
||||
} catch (SocketTimeoutException STe) {
|
||||
return null;
|
||||
}
|
||||
if (-1 == rv) throw new EOFException(getString("transportReturnedEOF"));
|
||||
len[0] += rv;
|
||||
}
|
||||
if (len[0] == 0) return null;
|
||||
if (len[0] < 12) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Only got " + len[0] + " of 12 bytes of header");
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Parse the details from the header */
|
||||
byte endian = buf[0];
|
||||
byte type = buf[1];
|
||||
byte protover = buf[3];
|
||||
if (protover > Message.PROTOCOL) {
|
||||
buf = null;
|
||||
throw new MessageProtocolVersionException(MessageFormat.format(getString("protocolVersionUnsupported"), new Object[]{protover}));
|
||||
}
|
||||
|
||||
/* Read the length of the variable header */
|
||||
if (null == tbuf) {
|
||||
tbuf = new byte[4];
|
||||
len[1] = 0;
|
||||
}
|
||||
if (len[1] < 4) {
|
||||
try {
|
||||
rv = in.read(tbuf, len[1], 4 - len[1]);
|
||||
} catch (SocketTimeoutException STe) {
|
||||
return null;
|
||||
}
|
||||
if (-1 == rv) throw new EOFException(getString("transportReturnedEOF"));
|
||||
len[1] += rv;
|
||||
}
|
||||
if (len[1] < 4) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Only got " + len[1] + " of 4 bytes of header");
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Parse the variable header length */
|
||||
int headerlen = 0;
|
||||
if (null == header) {
|
||||
headerlen = (int) Message.demarshallint(tbuf, 0, endian, 4);
|
||||
if (0 != headerlen % 8)
|
||||
headerlen += 8 - (headerlen % 8);
|
||||
} else
|
||||
headerlen = header.length - 8;
|
||||
|
||||
/* Read the variable header */
|
||||
if (null == header) {
|
||||
header = new byte[headerlen + 8];
|
||||
System.arraycopy(tbuf, 0, header, 0, 4);
|
||||
len[2] = 0;
|
||||
}
|
||||
if (len[2] < headerlen) {
|
||||
try {
|
||||
rv = in.read(header, 8 + len[2], headerlen - len[2]);
|
||||
} catch (SocketTimeoutException STe) {
|
||||
return null;
|
||||
}
|
||||
if (-1 == rv) throw new EOFException(getString("transportReturnedEOF"));
|
||||
len[2] += rv;
|
||||
}
|
||||
if (len[2] < headerlen) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Only got " + len[2] + " of " + headerlen + " bytes of header");
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Read the body */
|
||||
int bodylen = 0;
|
||||
if (null == body) bodylen = (int) Message.demarshallint(buf, 4, endian, 4);
|
||||
if (null == body) {
|
||||
body = new byte[bodylen];
|
||||
len[3] = 0;
|
||||
}
|
||||
if (len[3] < body.length) {
|
||||
try {
|
||||
rv = in.read(body, len[3], body.length - len[3]);
|
||||
} catch (SocketTimeoutException STe) {
|
||||
return null;
|
||||
}
|
||||
if (-1 == rv) throw new EOFException(getString("transportReturnedEOF"));
|
||||
len[3] += rv;
|
||||
}
|
||||
if (len[3] < body.length) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Only got " + len[3] + " of " + body.length + " bytes of body");
|
||||
return null;
|
||||
}
|
||||
|
||||
Message m;
|
||||
switch (type) {
|
||||
case Message.MessageType.METHOD_CALL:
|
||||
m = new MethodCall();
|
||||
break;
|
||||
case Message.MessageType.METHOD_RETURN:
|
||||
m = new MethodReturn();
|
||||
break;
|
||||
case Message.MessageType.SIGNAL:
|
||||
m = new DBusSignal();
|
||||
break;
|
||||
case Message.MessageType.ERROR:
|
||||
m = new Error();
|
||||
break;
|
||||
default:
|
||||
throw new MessageTypeException(MessageFormat.format(getString("messageTypeUnsupported"), new Object[]{type}));
|
||||
}
|
||||
if (Debug.debug) {
|
||||
Debug.print(Debug.VERBOSE, Hexdump.format(buf));
|
||||
Debug.print(Debug.VERBOSE, Hexdump.format(tbuf));
|
||||
Debug.print(Debug.VERBOSE, Hexdump.format(header));
|
||||
Debug.print(Debug.VERBOSE, Hexdump.format(body));
|
||||
}
|
||||
try {
|
||||
m.populate(buf, header, body);
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
buf = null;
|
||||
tbuf = null;
|
||||
body = null;
|
||||
header = null;
|
||||
throw DBe;
|
||||
} catch (RuntimeException Re) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, Re);
|
||||
buf = null;
|
||||
tbuf = null;
|
||||
body = null;
|
||||
header = null;
|
||||
throw Re;
|
||||
}
|
||||
if (Debug.debug) {
|
||||
Debug.print(Debug.INFO, "=> " + m);
|
||||
}
|
||||
buf = null;
|
||||
tbuf = null;
|
||||
body = null;
|
||||
header = null;
|
||||
return m;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Closing Message Reader");
|
||||
in.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import cx.ath.matthew.unix.USOutputStream;
|
||||
import cx.ath.matthew.utils.Hexdump;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class MessageWriter {
|
||||
private OutputStream out;
|
||||
private boolean isunix;
|
||||
|
||||
public MessageWriter(OutputStream out) {
|
||||
this.out = out;
|
||||
this.isunix = false;
|
||||
try {
|
||||
if (out instanceof USOutputStream)
|
||||
this.isunix = true;
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
if (!this.isunix)
|
||||
this.out = new BufferedOutputStream(this.out);
|
||||
}
|
||||
|
||||
public void writeMessage(Message m) throws IOException {
|
||||
if (Debug.debug) {
|
||||
Debug.print(Debug.INFO, "<= " + m);
|
||||
}
|
||||
if (null == m) return;
|
||||
if (null == m.getWireData()) {
|
||||
if (Debug.debug) Debug.print(Debug.WARN, "Message " + m + " wire-data was null!");
|
||||
return;
|
||||
}
|
||||
if (isunix) {
|
||||
if (Debug.debug) {
|
||||
Debug.print(Debug.DEBUG, "Writing all " + m.getWireData().length + " buffers simultaneously to Unix Socket");
|
||||
for (byte[] buf : m.getWireData())
|
||||
Debug.print(Debug.VERBOSE, "(" + buf + "):" + (null == buf ? "" : Hexdump.format(buf)));
|
||||
}
|
||||
((USOutputStream) out).write(m.getWireData());
|
||||
} else
|
||||
for (byte[] buf : m.getWireData()) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "(" + buf + "):" + (null == buf ? "" : Hexdump.format(buf)));
|
||||
if (null == buf) break;
|
||||
out.write(buf);
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Closing Message Writer");
|
||||
out.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import cx.ath.matthew.utils.Hexdump;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.MessageFormatException;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class MethodCall extends Message {
|
||||
MethodCall() {
|
||||
}
|
||||
|
||||
public MethodCall(String dest, String path, String iface, String member, byte flags, String sig, Object... args) throws DBusException {
|
||||
this(null, dest, path, iface, member, flags, sig, args);
|
||||
}
|
||||
|
||||
public MethodCall(String source, String dest, String path, String iface, String member, byte flags, String sig, Object... args) throws DBusException {
|
||||
super(Message.Endian.BIG, Message.MessageType.METHOD_CALL, flags);
|
||||
|
||||
if (null == member || null == path)
|
||||
throw new MessageFormatException(getString("missingDestinationPathFunction"));
|
||||
headers.put(Message.HeaderField.PATH, path);
|
||||
headers.put(Message.HeaderField.MEMBER, member);
|
||||
|
||||
Vector<Object> hargs = new Vector<Object>();
|
||||
|
||||
hargs.add(new Object[]{Message.HeaderField.PATH, new Object[]{ArgumentType.OBJECT_PATH_STRING, path}});
|
||||
|
||||
if (null != source) {
|
||||
headers.put(Message.HeaderField.SENDER, source);
|
||||
hargs.add(new Object[]{Message.HeaderField.SENDER, new Object[]{ArgumentType.STRING_STRING, source}});
|
||||
}
|
||||
|
||||
if (null != dest) {
|
||||
headers.put(Message.HeaderField.DESTINATION, dest);
|
||||
hargs.add(new Object[]{Message.HeaderField.DESTINATION, new Object[]{ArgumentType.STRING_STRING, dest}});
|
||||
}
|
||||
|
||||
if (null != iface) {
|
||||
hargs.add(new Object[]{Message.HeaderField.INTERFACE, new Object[]{ArgumentType.STRING_STRING, iface}});
|
||||
headers.put(Message.HeaderField.INTERFACE, iface);
|
||||
}
|
||||
|
||||
hargs.add(new Object[]{Message.HeaderField.MEMBER, new Object[]{ArgumentType.STRING_STRING, member}});
|
||||
|
||||
if (null != sig) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Appending arguments with signature: " + sig);
|
||||
hargs.add(new Object[]{Message.HeaderField.SIGNATURE, new Object[]{ArgumentType.SIGNATURE_STRING, sig}});
|
||||
headers.put(Message.HeaderField.SIGNATURE, sig);
|
||||
setArgs(args);
|
||||
}
|
||||
|
||||
byte[] blen = new byte[4];
|
||||
appendBytes(blen);
|
||||
append("ua(yv)", serial, hargs.toArray());
|
||||
pad((byte) 8);
|
||||
|
||||
long c = bytecounter;
|
||||
if (null != sig) append(sig, args);
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Appended body, type: " + sig + " start: " + c + " end: " + bytecounter + " size: " + (bytecounter - c));
|
||||
marshallint(bytecounter - c, blen, 0, 4);
|
||||
if (Debug.debug) Debug.print("marshalled size (" + blen + "): " + Hexdump.format(blen));
|
||||
}
|
||||
|
||||
private static long REPLY_WAIT_TIMEOUT = 20000;
|
||||
|
||||
/**
|
||||
* Set the default timeout for method calls.
|
||||
* Default is 20s.
|
||||
*
|
||||
* @param timeout New timeout in ms.
|
||||
*/
|
||||
public static void setDefaultTimeout(long timeout) {
|
||||
REPLY_WAIT_TIMEOUT = timeout;
|
||||
}
|
||||
|
||||
Message reply = null;
|
||||
|
||||
public synchronized boolean hasReply() {
|
||||
return null != reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block (if neccessary) for a reply.
|
||||
*
|
||||
* @param timeout The length of time to block before timing out (ms).
|
||||
* @return The reply to this MethodCall, or null if a timeout happens.
|
||||
*/
|
||||
public synchronized Message getReply(long timeout) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Blocking on " + this);
|
||||
if (null != reply) return reply;
|
||||
try {
|
||||
wait(timeout);
|
||||
return reply;
|
||||
} catch (InterruptedException Ie) {
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block (if neccessary) for a reply.
|
||||
* Default timeout is 20s, or can be configured with setDefaultTimeout()
|
||||
*
|
||||
* @return The reply to this MethodCall, or null if a timeout happens.
|
||||
*/
|
||||
public synchronized Message getReply() {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Blocking on " + this);
|
||||
if (null != reply) return reply;
|
||||
try {
|
||||
wait(REPLY_WAIT_TIMEOUT);
|
||||
return reply;
|
||||
} catch (InterruptedException Ie) {
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void setReply(Message reply) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Setting reply to " + this + " to " + reply);
|
||||
this.reply = reply;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
public class MethodReturn extends Message {
|
||||
MethodReturn() {
|
||||
}
|
||||
|
||||
public MethodReturn(String dest, long replyserial, String sig, Object... args) throws DBusException {
|
||||
this(null, dest, replyserial, sig, args);
|
||||
}
|
||||
|
||||
public MethodReturn(String source, String dest, long replyserial, String sig, Object... args) throws DBusException {
|
||||
super(Message.Endian.BIG, Message.MessageType.METHOD_RETURN, (byte) 0);
|
||||
|
||||
headers.put(Message.HeaderField.REPLY_SERIAL, replyserial);
|
||||
|
||||
Vector<Object> hargs = new Vector<Object>();
|
||||
hargs.add(new Object[]{Message.HeaderField.REPLY_SERIAL, new Object[]{ArgumentType.UINT32_STRING, replyserial}});
|
||||
|
||||
if (null != source) {
|
||||
headers.put(Message.HeaderField.SENDER, source);
|
||||
hargs.add(new Object[]{Message.HeaderField.SENDER, new Object[]{ArgumentType.STRING_STRING, source}});
|
||||
}
|
||||
|
||||
if (null != dest) {
|
||||
headers.put(Message.HeaderField.DESTINATION, dest);
|
||||
hargs.add(new Object[]{Message.HeaderField.DESTINATION, new Object[]{ArgumentType.STRING_STRING, dest}});
|
||||
}
|
||||
|
||||
if (null != sig) {
|
||||
hargs.add(new Object[]{Message.HeaderField.SIGNATURE, new Object[]{ArgumentType.SIGNATURE_STRING, sig}});
|
||||
headers.put(Message.HeaderField.SIGNATURE, sig);
|
||||
setArgs(args);
|
||||
}
|
||||
|
||||
byte[] blen = new byte[4];
|
||||
appendBytes(blen);
|
||||
append("ua(yv)", serial, hargs.toArray());
|
||||
pad((byte) 8);
|
||||
|
||||
long c = bytecounter;
|
||||
if (null != sig) append(sig, args);
|
||||
marshallint(bytecounter - c, blen, 0, 4);
|
||||
}
|
||||
|
||||
public MethodReturn(MethodCall mc, String sig, Object... args) throws DBusException {
|
||||
this(null, mc, sig, args);
|
||||
}
|
||||
|
||||
public MethodReturn(String source, MethodCall mc, String sig, Object... args) throws DBusException {
|
||||
this(source, mc.getSource(), mc.getSerial(), sig, args);
|
||||
this.call = mc;
|
||||
}
|
||||
|
||||
MethodCall call;
|
||||
|
||||
public MethodCall getCall() {
|
||||
return call;
|
||||
}
|
||||
|
||||
protected void setCall(MethodCall call) {
|
||||
this.call = call;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
class MethodTuple {
|
||||
String name;
|
||||
String sig;
|
||||
|
||||
public MethodTuple(String name, String sig) {
|
||||
this.name = name;
|
||||
if (null != sig)
|
||||
this.sig = sig;
|
||||
else
|
||||
this.sig = "";
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "new MethodTuple(" + this.name + ", " + this.sig + ")");
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return o.getClass().equals(MethodTuple.class)
|
||||
&& ((MethodTuple) o).name.equals(this.name)
|
||||
&& ((MethodTuple) o).sig.equals(this.sig);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return name.hashCode() + sig.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
class ObjectPath extends Path {
|
||||
public String source;
|
||||
|
||||
// public DBusConnection conn;
|
||||
public ObjectPath(String source, String path/*, DBusConnection conn*/) {
|
||||
super(path);
|
||||
this.source = source;
|
||||
// this.conn = conn;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Keeps track of the exported objects for introspection data
|
||||
*/
|
||||
class ObjectTree {
|
||||
class TreeNode {
|
||||
String name;
|
||||
ExportedObject object;
|
||||
String data;
|
||||
TreeNode right;
|
||||
TreeNode down;
|
||||
|
||||
public TreeNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TreeNode(String name, ExportedObject object, String data) {
|
||||
this.name = name;
|
||||
this.object = object;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
private TreeNode root;
|
||||
|
||||
public ObjectTree() {
|
||||
root = new TreeNode("");
|
||||
}
|
||||
|
||||
public static final Pattern slashpattern = Pattern.compile("/");
|
||||
|
||||
private TreeNode recursiveFind(TreeNode current, String path) {
|
||||
if ("/".equals(path)) return current;
|
||||
String[] elements = path.split("/", 2);
|
||||
// this is us or a parent node
|
||||
if (path.startsWith(current.name)) {
|
||||
// this is us
|
||||
if (path.equals(current.name)) {
|
||||
return current;
|
||||
}
|
||||
// recurse down
|
||||
else {
|
||||
if (current.down == null)
|
||||
return null;
|
||||
else return recursiveFind(current.down, elements[1]);
|
||||
}
|
||||
} else if (current.right == null) {
|
||||
return null;
|
||||
} else if (0 > current.right.name.compareTo(elements[0])) {
|
||||
return null;
|
||||
}
|
||||
// recurse right
|
||||
else {
|
||||
return recursiveFind(current.right, path);
|
||||
}
|
||||
}
|
||||
|
||||
private TreeNode recursiveAdd(TreeNode current, String path, ExportedObject object, String data) {
|
||||
String[] elements = slashpattern.split(path, 2);
|
||||
// this is us or a parent node
|
||||
if (path.startsWith(current.name)) {
|
||||
// this is us
|
||||
if (1 == elements.length || "".equals(elements[1])) {
|
||||
current.object = object;
|
||||
current.data = data;
|
||||
}
|
||||
// recurse down
|
||||
else {
|
||||
if (current.down == null) {
|
||||
String[] el = elements[1].split("/", 2);
|
||||
current.down = new TreeNode(el[0]);
|
||||
}
|
||||
current.down = recursiveAdd(current.down, elements[1], object, data);
|
||||
}
|
||||
}
|
||||
// need to create a new sub-tree on the end
|
||||
else if (current.right == null) {
|
||||
current.right = new TreeNode(elements[0]);
|
||||
current.right = recursiveAdd(current.right, path, object, data);
|
||||
}
|
||||
// need to insert here
|
||||
else if (0 > current.right.name.compareTo(elements[0])) {
|
||||
TreeNode t = new TreeNode(elements[0]);
|
||||
t.right = current.right;
|
||||
current.right = t;
|
||||
current.right = recursiveAdd(current.right, path, object, data);
|
||||
}
|
||||
// recurse right
|
||||
else {
|
||||
current.right = recursiveAdd(current.right, path, object, data);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
public void add(String path, ExportedObject object, String data) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Adding " + path + " to object tree");
|
||||
root = recursiveAdd(root, path, object, data);
|
||||
}
|
||||
|
||||
public void remove(String path) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Removing " + path + " from object tree");
|
||||
TreeNode t = recursiveFind(root, path);
|
||||
t.object = null;
|
||||
t.data = null;
|
||||
}
|
||||
|
||||
public String Introspect(String path) {
|
||||
TreeNode t = recursiveFind(root, path);
|
||||
if (null == t) return null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<node name=\"");
|
||||
sb.append(path);
|
||||
sb.append("\">\n");
|
||||
if (null != t.data) sb.append(t.data);
|
||||
t = t.down;
|
||||
while (null != t) {
|
||||
sb.append("<node name=\"");
|
||||
sb.append(t.name);
|
||||
sb.append("\"/>\n");
|
||||
t = t.right;
|
||||
}
|
||||
sb.append("</node>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String recursivePrint(TreeNode current) {
|
||||
String s = "";
|
||||
if (null != current) {
|
||||
s += current.name;
|
||||
if (null != current.object)
|
||||
s += "*";
|
||||
if (null != current.down)
|
||||
s += "/{" + recursivePrint(current.down) + "}";
|
||||
if (null != current.right)
|
||||
s += ", " + recursivePrint(current.right);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return recursivePrint(root);
|
||||
}
|
||||
}
|
39
federation/sssd/src/main/java/org/freedesktop/dbus/Path.java
Normal file
39
federation/sssd/src/main/java/org/freedesktop/dbus/Path.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
public class Path implements Comparable<Path> {
|
||||
protected String path;
|
||||
|
||||
public Path(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof Path) && path.equals(((Path) other).path);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return path.hashCode();
|
||||
}
|
||||
|
||||
public int compareTo(Path that) {
|
||||
return path.compareTo(that.path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Position annotation, to annotate Struct fields
|
||||
* to be sent over DBus.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Position {
|
||||
/**
|
||||
* The order of this field in the Struct.
|
||||
*/
|
||||
int value();
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.DBus;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||
import org.freedesktop.dbus.exceptions.NotConnected;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
class RemoteInvocationHandler implements InvocationHandler {
|
||||
public static final int CALL_TYPE_SYNC = 0;
|
||||
public static final int CALL_TYPE_ASYNC = 1;
|
||||
public static final int CALL_TYPE_CALLBACK = 2;
|
||||
|
||||
public static Object convertRV(String sig, Object[] rp, Method m, AbstractConnection conn) throws DBusException {
|
||||
Class<? extends Object> c = m.getReturnType();
|
||||
|
||||
if (null == rp) {
|
||||
if (null == c || Void.TYPE.equals(c)) return null;
|
||||
else throw new DBusExecutionException(getString("voidReturnType"));
|
||||
} else {
|
||||
try {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "Converting return parameters from " + Arrays.deepToString(rp) + " to type " + m.getGenericReturnType());
|
||||
rp = Marshalling.deSerializeParameters(rp,
|
||||
new Type[]{m.getGenericReturnType()}, conn);
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusExecutionException(MessageFormat.format(getString("invalidReturnType"), new Object[]{e.getMessage()}));
|
||||
}
|
||||
}
|
||||
|
||||
switch (rp.length) {
|
||||
case 0:
|
||||
if (null == c || Void.TYPE.equals(c))
|
||||
return null;
|
||||
else throw new DBusExecutionException(getString("voidReturnType"));
|
||||
case 1:
|
||||
return rp[0];
|
||||
default:
|
||||
|
||||
// check we are meant to return multiple values
|
||||
if (!Tuple.class.isAssignableFrom(c))
|
||||
throw new DBusExecutionException(getString("tupleReturnType"));
|
||||
|
||||
Constructor<? extends Object> cons = c.getConstructors()[0];
|
||||
try {
|
||||
return cons.newInstance(rp);
|
||||
} catch (Exception e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object executeRemoteMethod(RemoteObject ro, Method m, AbstractConnection conn, int syncmethod, CallbackHandler callback, Object... args) throws DBusExecutionException {
|
||||
Type[] ts = m.getGenericParameterTypes();
|
||||
String sig = null;
|
||||
if (ts.length > 0) try {
|
||||
sig = Marshalling.getDBusType(ts);
|
||||
args = Marshalling.convertParameters(args, ts, conn);
|
||||
} catch (DBusException DBe) {
|
||||
throw new DBusExecutionException(getString("contructDBusTypeFailure") + DBe.getMessage());
|
||||
}
|
||||
MethodCall call;
|
||||
byte flags = 0;
|
||||
if (!ro.autostart) flags |= Message.Flags.NO_AUTO_START;
|
||||
if (syncmethod == CALL_TYPE_ASYNC) flags |= Message.Flags.ASYNC;
|
||||
if (m.isAnnotationPresent(DBus.Method.NoReply.class)) flags |= Message.Flags.NO_REPLY_EXPECTED;
|
||||
try {
|
||||
String name;
|
||||
if (m.isAnnotationPresent(DBusMemberName.class))
|
||||
name = m.getAnnotation(DBusMemberName.class).value();
|
||||
else
|
||||
name = m.getName();
|
||||
if (null == ro.iface)
|
||||
call = new MethodCall(ro.busname, ro.objectpath, null, name, flags, sig, args);
|
||||
else {
|
||||
if (null != ro.iface.getAnnotation(DBusInterfaceName.class)) {
|
||||
call = new MethodCall(ro.busname, ro.objectpath, ro.iface.getAnnotation(DBusInterfaceName.class).value(), name, flags, sig, args);
|
||||
} else
|
||||
call = new MethodCall(ro.busname, ro.objectpath, AbstractConnection.dollar_pattern.matcher(ro.iface.getName()).replaceAll("."), name, flags, sig, args);
|
||||
}
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
throw new DBusExecutionException(getString("constructOutgoingMethodCallFailure") + DBe.getMessage());
|
||||
}
|
||||
if (null == conn.outgoing) throw new NotConnected(getString("notConnected"));
|
||||
|
||||
switch (syncmethod) {
|
||||
case CALL_TYPE_ASYNC:
|
||||
conn.queueOutgoing(call);
|
||||
return new DBusAsyncReply(call, m, conn);
|
||||
case CALL_TYPE_CALLBACK:
|
||||
synchronized (conn.pendingCallbacks) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Queueing Callback " + callback + " for " + call);
|
||||
conn.pendingCallbacks.put(call, callback);
|
||||
conn.pendingCallbackReplys.put(call, new DBusAsyncReply(call, m, conn));
|
||||
}
|
||||
conn.queueOutgoing(call);
|
||||
return null;
|
||||
case CALL_TYPE_SYNC:
|
||||
conn.queueOutgoing(call);
|
||||
break;
|
||||
}
|
||||
|
||||
// get reply
|
||||
if (m.isAnnotationPresent(DBus.Method.NoReply.class)) return null;
|
||||
|
||||
Message reply = call.getReply();
|
||||
if (null == reply) throw new DBus.Error.NoReply(getString("notReplyWithSpecifiedTime"));
|
||||
|
||||
if (reply instanceof Error)
|
||||
((Error) reply).throwException();
|
||||
|
||||
try {
|
||||
return convertRV(reply.getSig(), reply.getParameters(), m, conn);
|
||||
} catch (DBusException e) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
|
||||
throw new DBusExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
AbstractConnection conn;
|
||||
RemoteObject remote;
|
||||
|
||||
public RemoteInvocationHandler(AbstractConnection conn, RemoteObject remote) {
|
||||
this.remote = remote;
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals("isRemote")) return true;
|
||||
else if (method.getName().equals("clone")) return null;
|
||||
else if (method.getName().equals("equals")) {
|
||||
try {
|
||||
if (1 == args.length)
|
||||
return new Boolean(remote.equals(((RemoteInvocationHandler) Proxy.getInvocationHandler(args[0])).remote));
|
||||
} catch (IllegalArgumentException IAe) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
} else if (method.getName().equals("finalize")) return null;
|
||||
else if (method.getName().equals("getClass")) return DBusInterface.class;
|
||||
else if (method.getName().equals("hashCode")) return remote.hashCode();
|
||||
else if (method.getName().equals("notify")) {
|
||||
remote.notify();
|
||||
return null;
|
||||
} else if (method.getName().equals("notifyAll")) {
|
||||
remote.notifyAll();
|
||||
return null;
|
||||
} else if (method.getName().equals("wait")) {
|
||||
if (0 == args.length) remote.wait();
|
||||
else if (1 == args.length
|
||||
&& args[0] instanceof Long) remote.wait((Long) args[0]);
|
||||
else if (2 == args.length
|
||||
&& args[0] instanceof Long
|
||||
&& args[1] instanceof Integer)
|
||||
remote.wait((Long) args[0], (Integer) args[1]);
|
||||
if (args.length <= 2)
|
||||
return null;
|
||||
} else if (method.getName().equals("toString"))
|
||||
return remote.toString();
|
||||
|
||||
return executeRemoteMethod(remote, method, conn, CALL_TYPE_SYNC, null, args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
class RemoteObject {
|
||||
String busname;
|
||||
String objectpath;
|
||||
Class<? extends DBusInterface> iface;
|
||||
boolean autostart;
|
||||
|
||||
public RemoteObject(String busname, String objectpath, Class<? extends DBusInterface> iface, boolean autostart) {
|
||||
this.busname = busname;
|
||||
this.objectpath = objectpath;
|
||||
this.iface = iface;
|
||||
this.autostart = autostart;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof RemoteObject)) return false;
|
||||
RemoteObject them = (RemoteObject) o;
|
||||
|
||||
if (!them.objectpath.equals(this.objectpath)) return false;
|
||||
|
||||
if (null == this.busname && null != them.busname) return false;
|
||||
if (null != this.busname && null == them.busname) return false;
|
||||
if (null != them.busname && !them.busname.equals(this.busname)) return false;
|
||||
|
||||
if (null == this.iface && null != them.iface) return false;
|
||||
if (null != this.iface && null == them.iface) return false;
|
||||
if (null != them.iface && !them.iface.equals(this.iface)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (null == busname ? 0 : busname.hashCode()) + objectpath.hashCode() +
|
||||
(null == iface ? 0 : iface.hashCode());
|
||||
}
|
||||
|
||||
public boolean autoStarting() {
|
||||
return autostart;
|
||||
}
|
||||
|
||||
public String getBusName() {
|
||||
return busname;
|
||||
}
|
||||
|
||||
public String getObjectPath() {
|
||||
return objectpath;
|
||||
}
|
||||
|
||||
public Class<? extends DBusInterface> getInterface() {
|
||||
return iface;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return busname + ":" + objectpath + ":" + iface;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
class SignalTuple {
|
||||
String type;
|
||||
String name;
|
||||
String object;
|
||||
String source;
|
||||
|
||||
public SignalTuple(String type, String name, String object, String source) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.object = object;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof SignalTuple)) return false;
|
||||
SignalTuple other = (SignalTuple) o;
|
||||
if (null == this.type && null != other.type) return false;
|
||||
if (null != this.type && !this.type.equals(other.type)) return false;
|
||||
if (null == this.name && null != other.name) return false;
|
||||
if (null != this.name && !this.name.equals(other.name)) return false;
|
||||
if (null == this.object && null != other.object) return false;
|
||||
if (null != this.object && !this.object.equals(other.object)) return false;
|
||||
if (null == this.source && null != other.source) return false;
|
||||
if (null != this.source && !this.source.equals(other.source)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (null == type ? 0 : type.hashCode())
|
||||
+ (null == name ? 0 : name.hashCode())
|
||||
+ (null == source ? 0 : source.hashCode())
|
||||
+ (null == object ? 0 : object.hashCode());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "SignalTuple(" + type + "," + name + "," + object + "," + source + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* An alternative to a WeakReference when you don't want
|
||||
* that behaviour.
|
||||
*/
|
||||
public class StrongReference<T> extends WeakReference<T> {
|
||||
T referant;
|
||||
|
||||
public StrongReference(T referant) {
|
||||
super(referant);
|
||||
this.referant = referant;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
referant = null;
|
||||
}
|
||||
|
||||
public boolean enqueue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return referant;
|
||||
}
|
||||
|
||||
public boolean isEnqueued() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* This class should be extended to create Structs.
|
||||
* Any such class may be sent over DBus to a method which takes a Struct.
|
||||
* All fields in the Struct which you wish to be serialized and sent to the
|
||||
* remote method should be annotated with the org.freedesktop.dbus.Position
|
||||
* annotation, in the order they should appear in to Struct to DBus.
|
||||
*/
|
||||
public abstract class Struct extends Container {
|
||||
public Struct() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,835 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import cx.ath.matthew.unix.UnixSocket;
|
||||
import cx.ath.matthew.unix.UnixSocketAddress;
|
||||
import cx.ath.matthew.utils.Hexdump;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.Collator;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
public class Transport {
|
||||
public static class SASL {
|
||||
public static class Command {
|
||||
private int command;
|
||||
private int mechs;
|
||||
private String data;
|
||||
private String response;
|
||||
|
||||
public Command() {
|
||||
}
|
||||
|
||||
public Command(String s) throws IOException {
|
||||
String[] ss = s.split(" ");
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Creating command from: " + Arrays.toString(ss));
|
||||
if (0 == col.compare(ss[0], "OK")) {
|
||||
command = COMMAND_OK;
|
||||
data = ss[1];
|
||||
} else if (0 == col.compare(ss[0], "AUTH")) {
|
||||
command = COMMAND_AUTH;
|
||||
if (ss.length > 1) {
|
||||
if (0 == col.compare(ss[1], "EXTERNAL"))
|
||||
mechs = AUTH_EXTERNAL;
|
||||
else if (0 == col.compare(ss[1], "DBUS_COOKIE_SHA1"))
|
||||
mechs = AUTH_SHA;
|
||||
else if (0 == col.compare(ss[1], "ANONYMOUS"))
|
||||
mechs = AUTH_ANON;
|
||||
}
|
||||
if (ss.length > 2)
|
||||
data = ss[2];
|
||||
} else if (0 == col.compare(ss[0], "DATA")) {
|
||||
command = COMMAND_DATA;
|
||||
data = ss[1];
|
||||
} else if (0 == col.compare(ss[0], "REJECTED")) {
|
||||
command = COMMAND_REJECTED;
|
||||
for (int i = 1; i < ss.length; i++)
|
||||
if (0 == col.compare(ss[i], "EXTERNAL"))
|
||||
mechs |= AUTH_EXTERNAL;
|
||||
else if (0 == col.compare(ss[i], "DBUS_COOKIE_SHA1"))
|
||||
mechs |= AUTH_SHA;
|
||||
else if (0 == col.compare(ss[i], "ANONYMOUS"))
|
||||
mechs |= AUTH_ANON;
|
||||
} else if (0 == col.compare(ss[0], "BEGIN")) {
|
||||
command = COMMAND_BEGIN;
|
||||
} else if (0 == col.compare(ss[0], "CANCEL")) {
|
||||
command = COMMAND_CANCEL;
|
||||
} else if (0 == col.compare(ss[0], "ERROR")) {
|
||||
command = COMMAND_ERROR;
|
||||
data = ss[1];
|
||||
} else {
|
||||
throw new IOException(getString("invalidCommand") + ss[0]);
|
||||
}
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Created command: " + this);
|
||||
}
|
||||
|
||||
public int getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public int getMechs() {
|
||||
return mechs;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(String s) {
|
||||
response = s;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Command(" + command + ", " + mechs + ", " + data + ", " + null + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static Collator col = Collator.getInstance();
|
||||
|
||||
static {
|
||||
col.setDecomposition(Collator.FULL_DECOMPOSITION);
|
||||
col.setStrength(Collator.PRIMARY);
|
||||
}
|
||||
|
||||
public static final int LOCK_TIMEOUT = 1000;
|
||||
public static final int NEW_KEY_TIMEOUT_SECONDS = 60 * 5;
|
||||
public static final int EXPIRE_KEYS_TIMEOUT_SECONDS = NEW_KEY_TIMEOUT_SECONDS + (60 * 2);
|
||||
public static final int MAX_TIME_TRAVEL_SECONDS = 60 * 5;
|
||||
public static final int COOKIE_TIMEOUT = 240;
|
||||
public static final String COOKIE_CONTEXT = "org_freedesktop_java";
|
||||
|
||||
private String findCookie(String context, String ID) throws IOException {
|
||||
String homedir = System.getProperty("user.home");
|
||||
File f = new File(homedir + "/.dbus-keyrings/" + context);
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
|
||||
String s = null;
|
||||
String cookie = null;
|
||||
long now = System.currentTimeMillis() / 1000;
|
||||
while (null != (s = r.readLine())) {
|
||||
String[] line = s.split(" ");
|
||||
long timestamp = Long.parseLong(line[1]);
|
||||
if (line[0].equals(ID) && (!(timestamp < 0 ||
|
||||
(now + MAX_TIME_TRAVEL_SECONDS) < timestamp ||
|
||||
(now - EXPIRE_KEYS_TIMEOUT_SECONDS) > timestamp))) {
|
||||
cookie = line[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
r.close();
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private void addCookie(String context, String ID, long timestamp, String cookie) throws IOException {
|
||||
String homedir = System.getProperty("user.home");
|
||||
File keydir = new File(homedir + "/.dbus-keyrings/");
|
||||
File cookiefile = new File(homedir + "/.dbus-keyrings/" + context);
|
||||
File lock = new File(homedir + "/.dbus-keyrings/" + context + ".lock");
|
||||
File temp = new File(homedir + "/.dbus-keyrings/" + context + ".temp");
|
||||
|
||||
// ensure directory exists
|
||||
if (!keydir.exists()) keydir.mkdirs();
|
||||
|
||||
// acquire lock
|
||||
long start = System.currentTimeMillis();
|
||||
while (!lock.createNewFile() && LOCK_TIMEOUT > (System.currentTimeMillis() - start)) ;
|
||||
|
||||
// read old file
|
||||
Vector<String> lines = new Vector<String>();
|
||||
if (cookiefile.exists()) {
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(cookiefile)));
|
||||
String s = null;
|
||||
while (null != (s = r.readLine())) {
|
||||
String[] line = s.split(" ");
|
||||
long time = Long.parseLong(line[1]);
|
||||
// expire stale cookies
|
||||
if ((timestamp - time) < COOKIE_TIMEOUT)
|
||||
lines.add(s);
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
|
||||
// add cookie
|
||||
lines.add(ID + " " + timestamp + " " + cookie);
|
||||
|
||||
// write temp file
|
||||
PrintWriter w = new PrintWriter(new FileOutputStream(temp));
|
||||
for (String l : lines)
|
||||
w.println(l);
|
||||
w.close();
|
||||
|
||||
// atomically move to old file
|
||||
if (!temp.renameTo(cookiefile)) {
|
||||
cookiefile.delete();
|
||||
temp.renameTo(cookiefile);
|
||||
}
|
||||
|
||||
// remove lock
|
||||
lock.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the string, encodes it as hex and then turns it into a string again.
|
||||
* No, I don't know why either.
|
||||
*/
|
||||
private String stupidlyEncode(String data) {
|
||||
return Hexdump.toHex(data.getBytes()).replaceAll(" ", "");
|
||||
}
|
||||
|
||||
private String stupidlyEncode(byte[] data) {
|
||||
return Hexdump.toHex(data).replaceAll(" ", "");
|
||||
}
|
||||
|
||||
private byte getNibble(char c) {
|
||||
switch (c) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return (byte) (c - '0');
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
return (byte) (c - 'A' + 10);
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
return (byte) (c - 'a' + 10);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private String stupidlyDecode(String data) {
|
||||
char[] cs = new char[data.length()];
|
||||
char[] res = new char[cs.length / 2];
|
||||
data.getChars(0, data.length(), cs, 0);
|
||||
for (int i = 0, j = 0; j < res.length; i += 2, j++) {
|
||||
int b = 0;
|
||||
b |= getNibble(cs[i]) << 4;
|
||||
b |= getNibble(cs[i + 1]);
|
||||
res[j] = (char) b;
|
||||
}
|
||||
return new String(res);
|
||||
}
|
||||
|
||||
public static final int MODE_SERVER = 1;
|
||||
public static final int MODE_CLIENT = 2;
|
||||
|
||||
public static final int AUTH_NONE = 0;
|
||||
public static final int AUTH_EXTERNAL = 1;
|
||||
public static final int AUTH_SHA = 2;
|
||||
public static final int AUTH_ANON = 4;
|
||||
|
||||
public static final int COMMAND_AUTH = 1;
|
||||
public static final int COMMAND_DATA = 2;
|
||||
public static final int COMMAND_REJECTED = 3;
|
||||
public static final int COMMAND_OK = 4;
|
||||
public static final int COMMAND_BEGIN = 5;
|
||||
public static final int COMMAND_CANCEL = 6;
|
||||
public static final int COMMAND_ERROR = 7;
|
||||
|
||||
public static final int INITIAL_STATE = 0;
|
||||
public static final int WAIT_DATA = 1;
|
||||
public static final int WAIT_OK = 2;
|
||||
public static final int WAIT_REJECT = 3;
|
||||
public static final int WAIT_AUTH = 4;
|
||||
public static final int WAIT_BEGIN = 5;
|
||||
public static final int AUTHENTICATED = 6;
|
||||
public static final int FAILED = 7;
|
||||
|
||||
public static final int OK = 1;
|
||||
public static final int CONTINUE = 2;
|
||||
public static final int ERROR = 3;
|
||||
public static final int REJECT = 4;
|
||||
|
||||
public Command receive(InputStream s) throws IOException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
top:
|
||||
while (true) {
|
||||
int c = s.read();
|
||||
switch (c) {
|
||||
case -1:
|
||||
throw new IOException("Stream unexpectedly short (broken pipe)");
|
||||
case 0:
|
||||
case '\r':
|
||||
continue;
|
||||
case '\n':
|
||||
break top;
|
||||
default:
|
||||
sb.append((char) c);
|
||||
}
|
||||
}
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "received: " + sb);
|
||||
try {
|
||||
return new Command(sb.toString());
|
||||
} catch (Exception e) {
|
||||
if (Debug.debug && AbstractConnection.EXCEPTION_DEBUG) Debug.print(Debug.ERR, e);
|
||||
return new Command();
|
||||
}
|
||||
}
|
||||
|
||||
public void send(OutputStream out, int command, String... data) throws IOException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
switch (command) {
|
||||
case COMMAND_AUTH:
|
||||
sb.append("AUTH");
|
||||
break;
|
||||
case COMMAND_DATA:
|
||||
sb.append("DATA");
|
||||
break;
|
||||
case COMMAND_REJECTED:
|
||||
sb.append("REJECTED");
|
||||
break;
|
||||
case COMMAND_OK:
|
||||
sb.append("OK");
|
||||
break;
|
||||
case COMMAND_BEGIN:
|
||||
sb.append("BEGIN");
|
||||
break;
|
||||
case COMMAND_CANCEL:
|
||||
sb.append("CANCEL");
|
||||
break;
|
||||
case COMMAND_ERROR:
|
||||
sb.append("ERROR");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
for (String s : data) {
|
||||
sb.append(' ');
|
||||
sb.append(s);
|
||||
}
|
||||
sb.append('\r');
|
||||
sb.append('\n');
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "sending: " + sb);
|
||||
out.write(sb.toString().getBytes());
|
||||
}
|
||||
|
||||
public int do_challenge(int auth, Command c) throws IOException {
|
||||
switch (auth) {
|
||||
case AUTH_SHA:
|
||||
String[] reply = stupidlyDecode(c.getData()).split(" ");
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, Arrays.toString(reply));
|
||||
if (3 != reply.length) {
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Reply is not length 3");
|
||||
return ERROR;
|
||||
}
|
||||
String context = reply[0];
|
||||
String ID = reply[1];
|
||||
String serverchallenge = reply[2];
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA");
|
||||
} catch (NoSuchAlgorithmException NSAe) {
|
||||
if (Debug.debug && AbstractConnection.EXCEPTION_DEBUG) Debug.print(Debug.ERR, NSAe);
|
||||
return ERROR;
|
||||
}
|
||||
byte[] buf = new byte[8];
|
||||
Message.marshallintBig(System.currentTimeMillis(), buf, 0, 8);
|
||||
String clientchallenge = stupidlyEncode(md.digest(buf));
|
||||
md.reset();
|
||||
long start = System.currentTimeMillis();
|
||||
String cookie = null;
|
||||
while (null == cookie && (System.currentTimeMillis() - start) < LOCK_TIMEOUT)
|
||||
cookie = findCookie(context, ID);
|
||||
if (null == cookie) {
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Did not find a cookie in context " + context + " with ID " + ID);
|
||||
return ERROR;
|
||||
}
|
||||
String response = serverchallenge + ":" + clientchallenge + ":" + cookie;
|
||||
buf = md.digest(response.getBytes());
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.VERBOSE, "Response: " + response + " hash: " + Hexdump.format(buf));
|
||||
response = stupidlyEncode(buf);
|
||||
c.setResponse(stupidlyEncode(clientchallenge + " " + response));
|
||||
return OK;
|
||||
default:
|
||||
if (Debug.debug) Debug.print(Debug.DEBUG, "Not DBUS_COOKIE_SHA1 authtype.");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
public String challenge = "";
|
||||
public String cookie = "";
|
||||
|
||||
public int do_response(int auth, String Uid, String kernelUid, Command c) {
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA");
|
||||
} catch (NoSuchAlgorithmException NSAe) {
|
||||
if (Debug.debug && AbstractConnection.EXCEPTION_DEBUG) Debug.print(Debug.ERR, NSAe);
|
||||
return ERROR;
|
||||
}
|
||||
switch (auth) {
|
||||
case AUTH_NONE:
|
||||
switch (c.getMechs()) {
|
||||
case AUTH_ANON:
|
||||
return OK;
|
||||
case AUTH_EXTERNAL:
|
||||
if (0 == col.compare(Uid, c.getData()) &&
|
||||
(null == kernelUid || 0 == col.compare(Uid, kernelUid)))
|
||||
return OK;
|
||||
else
|
||||
return ERROR;
|
||||
case AUTH_SHA:
|
||||
String context = COOKIE_CONTEXT;
|
||||
long id = System.currentTimeMillis();
|
||||
byte[] buf = new byte[8];
|
||||
Message.marshallintBig(id, buf, 0, 8);
|
||||
challenge = stupidlyEncode(md.digest(buf));
|
||||
Random r = new Random();
|
||||
r.nextBytes(buf);
|
||||
cookie = stupidlyEncode(md.digest(buf));
|
||||
try {
|
||||
addCookie(context, "" + id, id / 1000, cookie);
|
||||
} catch (IOException IOe) {
|
||||
if (Debug.debug && AbstractConnection.EXCEPTION_DEBUG) Debug.print(Debug.ERR, IOe);
|
||||
}
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Sending challenge: " + context + ' ' + id + ' ' + challenge);
|
||||
c.setResponse(stupidlyEncode(context + ' ' + id + ' ' + challenge));
|
||||
return CONTINUE;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
case AUTH_SHA:
|
||||
String[] response = stupidlyDecode(c.getData()).split(" ");
|
||||
if (response.length < 2) return ERROR;
|
||||
String cchal = response[0];
|
||||
String hash = response[1];
|
||||
String prehash = challenge + ":" + cchal + ":" + cookie;
|
||||
byte[] buf = md.digest(prehash.getBytes());
|
||||
String posthash = stupidlyEncode(buf);
|
||||
if (Debug.debug)
|
||||
Debug.print(Debug.DEBUG, "Authenticating Hash; data=" + prehash + " remote hash=" + hash + " local hash=" + posthash);
|
||||
if (0 == col.compare(posthash, hash))
|
||||
return OK;
|
||||
else
|
||||
return ERROR;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getTypes(int types) {
|
||||
switch (types) {
|
||||
case AUTH_EXTERNAL:
|
||||
return new String[]{"EXTERNAL"};
|
||||
case AUTH_SHA:
|
||||
return new String[]{"DBUS_COOKIE_SHA1"};
|
||||
case AUTH_ANON:
|
||||
return new String[]{"ANONYMOUS"};
|
||||
case AUTH_SHA + AUTH_EXTERNAL:
|
||||
return new String[]{"EXTERNAL", "DBUS_COOKIE_SHA1"};
|
||||
case AUTH_SHA + AUTH_ANON:
|
||||
return new String[]{"ANONYMOUS", "DBUS_COOKIE_SHA1"};
|
||||
case AUTH_EXTERNAL + AUTH_ANON:
|
||||
return new String[]{"ANONYMOUS", "EXTERNAL"};
|
||||
case AUTH_EXTERNAL + AUTH_ANON + AUTH_SHA:
|
||||
return new String[]{"ANONYMOUS", "EXTERNAL", "DBUS_COOKIE_SHA1"};
|
||||
default:
|
||||
return new String[]{};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* performs SASL auth on the given streams.
|
||||
* Mode selects whether to run as a SASL server or client.
|
||||
* Types is a bitmask of the available auth types.
|
||||
* Returns true if the auth was successful and false if it failed.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean auth(int mode, int types, String guid, OutputStream out, InputStream in, UnixSocket us) throws IOException {
|
||||
String username = System.getProperty("user.name");
|
||||
String Uid = null;
|
||||
String kernelUid = null;
|
||||
try {
|
||||
Class c = Class.forName("com.sun.security.auth.module.UnixSystem");
|
||||
Method m = c.getMethod("getUid");
|
||||
Object o = c.newInstance();
|
||||
long uid = (Long) m.invoke(o);
|
||||
Uid = stupidlyEncode("" + uid);
|
||||
} catch (Exception e) {
|
||||
Uid = stupidlyEncode(username);
|
||||
}
|
||||
Command c;
|
||||
int failed = 0;
|
||||
int current = 0;
|
||||
int state = INITIAL_STATE;
|
||||
|
||||
while (state != AUTHENTICATED && state != FAILED) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "AUTH state: " + state);
|
||||
switch (mode) {
|
||||
case MODE_CLIENT:
|
||||
switch (state) {
|
||||
case INITIAL_STATE:
|
||||
if (null == us)
|
||||
out.write(new byte[]{0});
|
||||
else
|
||||
us.sendCredentialByte((byte) 0);
|
||||
send(out, COMMAND_AUTH);
|
||||
state = WAIT_DATA;
|
||||
break;
|
||||
case WAIT_DATA:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_DATA:
|
||||
switch (do_challenge(current, c)) {
|
||||
case CONTINUE:
|
||||
send(out, COMMAND_DATA, c.getResponse());
|
||||
break;
|
||||
case OK:
|
||||
send(out, COMMAND_DATA, c.getResponse());
|
||||
state = WAIT_OK;
|
||||
break;
|
||||
case ERROR:
|
||||
send(out, COMMAND_ERROR, c.getResponse());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case COMMAND_REJECTED:
|
||||
failed |= current;
|
||||
int available = c.getMechs() & (~failed);
|
||||
if (0 != (available & AUTH_EXTERNAL)) {
|
||||
send(out, COMMAND_AUTH, "EXTERNAL", Uid);
|
||||
current = AUTH_EXTERNAL;
|
||||
} else if (0 != (available & AUTH_SHA)) {
|
||||
send(out, COMMAND_AUTH, "DBUS_COOKIE_SHA1", Uid);
|
||||
current = AUTH_SHA;
|
||||
} else if (0 != (available & AUTH_ANON)) {
|
||||
send(out, COMMAND_AUTH, "ANONYMOUS");
|
||||
current = AUTH_ANON;
|
||||
} else state = FAILED;
|
||||
break;
|
||||
case COMMAND_ERROR:
|
||||
send(out, COMMAND_CANCEL);
|
||||
state = WAIT_REJECT;
|
||||
break;
|
||||
case COMMAND_OK:
|
||||
send(out, COMMAND_BEGIN);
|
||||
state = AUTHENTICATED;
|
||||
break;
|
||||
default:
|
||||
send(out, COMMAND_ERROR, "Got invalid command");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WAIT_OK:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_OK:
|
||||
send(out, COMMAND_BEGIN);
|
||||
state = AUTHENTICATED;
|
||||
break;
|
||||
case COMMAND_ERROR:
|
||||
case COMMAND_DATA:
|
||||
send(out, COMMAND_CANCEL);
|
||||
state = WAIT_REJECT;
|
||||
break;
|
||||
case COMMAND_REJECTED:
|
||||
failed |= current;
|
||||
int available = c.getMechs() & (~failed);
|
||||
state = WAIT_DATA;
|
||||
if (0 != (available & AUTH_EXTERNAL)) {
|
||||
send(out, COMMAND_AUTH, "EXTERNAL", Uid);
|
||||
current = AUTH_EXTERNAL;
|
||||
} else if (0 != (available & AUTH_SHA)) {
|
||||
send(out, COMMAND_AUTH, "DBUS_COOKIE_SHA1", Uid);
|
||||
current = AUTH_SHA;
|
||||
} else if (0 != (available & AUTH_ANON)) {
|
||||
send(out, COMMAND_AUTH, "ANONYMOUS");
|
||||
current = AUTH_ANON;
|
||||
} else state = FAILED;
|
||||
break;
|
||||
default:
|
||||
send(out, COMMAND_ERROR, "Got invalid command");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WAIT_REJECT:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_REJECTED:
|
||||
failed |= current;
|
||||
int available = c.getMechs() & (~failed);
|
||||
if (0 != (available & AUTH_EXTERNAL)) {
|
||||
send(out, COMMAND_AUTH, "EXTERNAL", Uid);
|
||||
current = AUTH_EXTERNAL;
|
||||
} else if (0 != (available & AUTH_SHA)) {
|
||||
send(out, COMMAND_AUTH, "DBUS_COOKIE_SHA1", Uid);
|
||||
current = AUTH_SHA;
|
||||
} else if (0 != (available & AUTH_ANON)) {
|
||||
send(out, COMMAND_AUTH, "ANONYMOUS");
|
||||
current = AUTH_ANON;
|
||||
} else state = FAILED;
|
||||
break;
|
||||
default:
|
||||
state = FAILED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
state = FAILED;
|
||||
}
|
||||
break;
|
||||
case MODE_SERVER:
|
||||
switch (state) {
|
||||
case INITIAL_STATE:
|
||||
byte[] buf = new byte[1];
|
||||
if (null == us) {
|
||||
in.read(buf);
|
||||
} else {
|
||||
buf[0] = us.recvCredentialByte();
|
||||
int kuid = us.getPeerUID();
|
||||
if (kuid >= 0)
|
||||
kernelUid = stupidlyEncode("" + kuid);
|
||||
}
|
||||
if (0 != buf[0]) state = FAILED;
|
||||
else state = WAIT_AUTH;
|
||||
break;
|
||||
case WAIT_AUTH:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_AUTH:
|
||||
if (null == c.getData()) {
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
} else {
|
||||
switch (do_response(current, Uid, kernelUid, c)) {
|
||||
case CONTINUE:
|
||||
send(out, COMMAND_DATA, c.getResponse());
|
||||
current = c.getMechs();
|
||||
state = WAIT_DATA;
|
||||
break;
|
||||
case OK:
|
||||
send(out, COMMAND_OK, guid);
|
||||
state = WAIT_BEGIN;
|
||||
current = 0;
|
||||
break;
|
||||
case REJECT:
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
current = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COMMAND_ERROR:
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
break;
|
||||
case COMMAND_BEGIN:
|
||||
state = FAILED;
|
||||
break;
|
||||
default:
|
||||
send(out, COMMAND_ERROR, "Got invalid command");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WAIT_DATA:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_DATA:
|
||||
switch (do_response(current, Uid, kernelUid, c)) {
|
||||
case CONTINUE:
|
||||
send(out, COMMAND_DATA, c.getResponse());
|
||||
state = WAIT_DATA;
|
||||
break;
|
||||
case OK:
|
||||
send(out, COMMAND_OK, guid);
|
||||
state = WAIT_BEGIN;
|
||||
current = 0;
|
||||
break;
|
||||
case REJECT:
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
current = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case COMMAND_ERROR:
|
||||
case COMMAND_CANCEL:
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
state = WAIT_AUTH;
|
||||
break;
|
||||
case COMMAND_BEGIN:
|
||||
state = FAILED;
|
||||
break;
|
||||
default:
|
||||
send(out, COMMAND_ERROR, "Got invalid command");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WAIT_BEGIN:
|
||||
c = receive(in);
|
||||
switch (c.getCommand()) {
|
||||
case COMMAND_ERROR:
|
||||
case COMMAND_CANCEL:
|
||||
send(out, COMMAND_REJECTED, getTypes(types));
|
||||
state = WAIT_AUTH;
|
||||
break;
|
||||
case COMMAND_BEGIN:
|
||||
state = AUTHENTICATED;
|
||||
break;
|
||||
default:
|
||||
send(out, COMMAND_ERROR, "Got invalid command");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
state = FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return state == AUTHENTICATED;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageReader min;
|
||||
public MessageWriter mout;
|
||||
|
||||
public Transport() {
|
||||
}
|
||||
|
||||
public static String genGUID() {
|
||||
Random r = new Random();
|
||||
byte[] buf = new byte[16];
|
||||
r.nextBytes(buf);
|
||||
String guid = Hexdump.toHex(buf);
|
||||
return guid.replaceAll(" ", "");
|
||||
}
|
||||
|
||||
public Transport(BusAddress address) throws IOException {
|
||||
connect(address);
|
||||
}
|
||||
|
||||
public Transport(String address) throws IOException, ParseException {
|
||||
connect(new BusAddress(address));
|
||||
}
|
||||
|
||||
public Transport(String address, int timeout) throws IOException, ParseException {
|
||||
connect(new BusAddress(address), timeout);
|
||||
}
|
||||
|
||||
public void connect(String address) throws IOException, ParseException {
|
||||
connect(new BusAddress(address), 0);
|
||||
}
|
||||
|
||||
public void connect(String address, int timeout) throws IOException, ParseException {
|
||||
connect(new BusAddress(address), timeout);
|
||||
}
|
||||
|
||||
public void connect(BusAddress address) throws IOException {
|
||||
connect(address, 0);
|
||||
}
|
||||
|
||||
public void connect(BusAddress address, int timeout) throws IOException {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Connecting to " + address);
|
||||
OutputStream out = null;
|
||||
InputStream in = null;
|
||||
UnixSocket us = null;
|
||||
Socket s = null;
|
||||
int mode = 0;
|
||||
int types = 0;
|
||||
if ("unix".equals(address.getType())) {
|
||||
types = SASL.AUTH_EXTERNAL;
|
||||
mode = SASL.MODE_CLIENT;
|
||||
us = new UnixSocket();
|
||||
if (null != address.getParameter("abstract"))
|
||||
us.connect(new UnixSocketAddress(address.getParameter("abstract"), true));
|
||||
else if (null != address.getParameter("path"))
|
||||
us.connect(new UnixSocketAddress(address.getParameter("path"), false));
|
||||
us.setPassCred(true);
|
||||
in = us.getInputStream();
|
||||
out = us.getOutputStream();
|
||||
} else if ("tcp".equals(address.getType())) {
|
||||
types = SASL.AUTH_SHA;
|
||||
if (null != address.getParameter("listen")) {
|
||||
mode = SASL.MODE_SERVER;
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(address.getParameter("host"), Integer.parseInt(address.getParameter("port"))));
|
||||
s = ss.accept();
|
||||
} else {
|
||||
mode = SASL.MODE_CLIENT;
|
||||
s = new Socket();
|
||||
s.connect(new InetSocketAddress(address.getParameter("host"), Integer.parseInt(address.getParameter("port"))));
|
||||
}
|
||||
in = s.getInputStream();
|
||||
out = s.getOutputStream();
|
||||
} else {
|
||||
throw new IOException(getString("unknownAddress") + address.getType());
|
||||
}
|
||||
|
||||
if (!(new SASL()).auth(mode, types, address.getParameter("guid"), out, in, us)) {
|
||||
out.close();
|
||||
throw new IOException(getString("errorAuth"));
|
||||
}
|
||||
if (null != us) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Setting timeout to " + timeout + " on Socket");
|
||||
if (timeout == 1)
|
||||
us.setBlocking(false);
|
||||
else
|
||||
us.setSoTimeout(timeout);
|
||||
}
|
||||
if (null != s) {
|
||||
if (Debug.debug) Debug.print(Debug.VERBOSE, "Setting timeout to " + timeout + " on Socket");
|
||||
s.setSoTimeout(timeout);
|
||||
}
|
||||
mout = new MessageWriter(out);
|
||||
min = new MessageReader(in);
|
||||
}
|
||||
|
||||
public void disconnect() throws IOException {
|
||||
if (Debug.debug) Debug.print(Debug.INFO, "Disconnecting Transport");
|
||||
min.close();
|
||||
mout.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
/**
|
||||
* This class should be extended to create Tuples.
|
||||
* Any such class may be used as the return type for a method
|
||||
* which returns multiple values.
|
||||
* All fields in the Tuple which you wish to be serialized and sent to the
|
||||
* remote method should be annotated with the org.freedesktop.dbus.Position
|
||||
* annotation, in the order they should appear to DBus.
|
||||
*/
|
||||
public abstract class Tuple extends Container {
|
||||
public Tuple() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class TypeSignature {
|
||||
String sig;
|
||||
|
||||
public TypeSignature(String sig) {
|
||||
this.sig = sig;
|
||||
}
|
||||
|
||||
public TypeSignature(Type[] types) throws DBusException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Type t : types) {
|
||||
String[] ts = Marshalling.getDBusType(t);
|
||||
for (String s : ts)
|
||||
sb.append(s);
|
||||
}
|
||||
this.sig = sb.toString();
|
||||
}
|
||||
|
||||
public String getSig() {
|
||||
return sig;
|
||||
}
|
||||
}
|
122
federation/sssd/src/main/java/org/freedesktop/dbus/UInt16.java
Normal file
122
federation/sssd/src/main/java/org/freedesktop/dbus/UInt16.java
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Class to represent 16-bit unsigned integers.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UInt16 extends Number implements Comparable<UInt16> {
|
||||
/**
|
||||
* Maximum possible value.
|
||||
*/
|
||||
public static final int MAX_VALUE = 65535;
|
||||
/**
|
||||
* Minimum possible value.
|
||||
*/
|
||||
public static final int MIN_VALUE = 0;
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Create a UInt16 from an int.
|
||||
*
|
||||
* @param value Must be within MIN_VALUE–MAX_VALUE
|
||||
* @throws NumberFormatException if value is not between MIN_VALUE and MAX_VALUE
|
||||
*/
|
||||
public UInt16(int value) {
|
||||
if (value < MIN_VALUE || value > MAX_VALUE)
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_VALUE}));
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UInt16 from a String.
|
||||
*
|
||||
* @param value Must parse to a valid integer within MIN_VALUE–MAX_VALUE
|
||||
* @throws NumberFormatException if value is not an integer between MIN_VALUE and MAX_VALUE
|
||||
*/
|
||||
public UInt16(String value) {
|
||||
this(Integer.parseInt(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a byte.
|
||||
*/
|
||||
public byte byteValue() {
|
||||
return (byte) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a double.
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a float.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a int.
|
||||
*/
|
||||
public int intValue() {
|
||||
return /*(int)*/ value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a long.
|
||||
*/
|
||||
public long longValue() {
|
||||
return (long) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a short.
|
||||
*/
|
||||
public short shortValue() {
|
||||
return (short) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two UInt16s for equality.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof UInt16 && ((UInt16) o).value == this.value;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return /*(int)*/ value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two UInt16s.
|
||||
*
|
||||
* @return 0 if equal, -ve or +ve if they are different.
|
||||
*/
|
||||
public int compareTo(UInt16 other) {
|
||||
return /*(int)*/ (this.value - other.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a string.
|
||||
*/
|
||||
public String toString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
122
federation/sssd/src/main/java/org/freedesktop/dbus/UInt32.java
Normal file
122
federation/sssd/src/main/java/org/freedesktop/dbus/UInt32.java
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Class to represent unsigned 32-bit numbers.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UInt32 extends Number implements Comparable<UInt32> {
|
||||
/**
|
||||
* Maximum allowed value
|
||||
*/
|
||||
public static final long MAX_VALUE = 4294967295L;
|
||||
/**
|
||||
* Minimum allowed value
|
||||
*/
|
||||
public static final long MIN_VALUE = 0;
|
||||
private long value;
|
||||
|
||||
/**
|
||||
* Create a UInt32 from a long.
|
||||
*
|
||||
* @param value Must be a valid integer within MIN_VALUE–MAX_VALUE
|
||||
* @throws NumberFormatException if value is not between MIN_VALUE and MAX_VALUE
|
||||
*/
|
||||
public UInt32(long value) {
|
||||
if (value < MIN_VALUE || value > MAX_VALUE)
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_VALUE}));
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UInt32 from a String.
|
||||
*
|
||||
* @param value Must parse to a valid integer within MIN_VALUE–MAX_VALUE
|
||||
* @throws NumberFormatException if value is not an integer between MIN_VALUE and MAX_VALUE
|
||||
*/
|
||||
public UInt32(String value) {
|
||||
this(Long.parseLong(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a byte.
|
||||
*/
|
||||
public byte byteValue() {
|
||||
return (byte) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a double.
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a float.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a int.
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a long.
|
||||
*/
|
||||
public long longValue() {
|
||||
return /*(long)*/ value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a short.
|
||||
*/
|
||||
public short shortValue() {
|
||||
return (short) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two UInt32s for equality.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof UInt32 && ((UInt32) o).value == this.value;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two UInt32s.
|
||||
*
|
||||
* @return 0 if equal, -ve or +ve if they are different.
|
||||
*/
|
||||
public int compareTo(UInt32 other) {
|
||||
return (int) (this.value - other.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a string
|
||||
*/
|
||||
public String toString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
203
federation/sssd/src/main/java/org/freedesktop/dbus/UInt64.java
Normal file
203
federation/sssd/src/main/java/org/freedesktop/dbus/UInt64.java
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* Class to represent unsigned 64-bit numbers.
|
||||
* Warning: Any functions which take or return a <tt>long</tt>
|
||||
* are restricted to the range of a signed 64bit number.
|
||||
* Use the BigInteger methods if you wish access to the full
|
||||
* range.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UInt64 extends Number implements Comparable<UInt64> {
|
||||
/**
|
||||
* Maximum allowed value (when accessed as a long)
|
||||
*/
|
||||
public static final long MAX_LONG_VALUE = Long.MAX_VALUE;
|
||||
/**
|
||||
* Maximum allowed value (when accessed as a BigInteger)
|
||||
*/
|
||||
public static final BigInteger MAX_BIG_VALUE = new BigInteger("18446744073709551615");
|
||||
/**
|
||||
* Minimum allowed value
|
||||
*/
|
||||
public static final long MIN_VALUE = 0;
|
||||
private BigInteger value;
|
||||
private long top;
|
||||
private long bottom;
|
||||
|
||||
/**
|
||||
* Create a UInt64 from a long.
|
||||
*
|
||||
* @param value Must be a valid integer within MIN_VALUE–MAX_VALUE
|
||||
* @throws NumberFormatException if value is not between MIN_VALUE and MAX_VALUE
|
||||
*/
|
||||
public UInt64(long value) {
|
||||
if (value < MIN_VALUE || value > MAX_LONG_VALUE)
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_LONG_VALUE}));
|
||||
this.value = new BigInteger("" + value);
|
||||
this.top = this.value.shiftRight(32).and(new BigInteger("4294967295")).longValue();
|
||||
this.bottom = this.value.and(new BigInteger("4294967295")).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UInt64 from two longs.
|
||||
*
|
||||
* @param top Most significant 4 bytes.
|
||||
* @param bottom Least significant 4 bytes.
|
||||
*/
|
||||
public UInt64(long top, long bottom) {
|
||||
BigInteger a = new BigInteger("" + top);
|
||||
a = a.shiftLeft(32);
|
||||
a = a.add(new BigInteger("" + bottom));
|
||||
if (0 > a.compareTo(BigInteger.ZERO))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{a, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
if (0 < a.compareTo(MAX_BIG_VALUE))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{a, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
this.value = a;
|
||||
this.top = top;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UInt64 from a BigInteger
|
||||
*
|
||||
* @param value Must be a valid BigInteger between MIN_VALUE–MAX_BIG_VALUE
|
||||
* @throws NumberFormatException if value is not an integer between MIN_VALUE and MAX_BIG_VALUE
|
||||
*/
|
||||
public UInt64(BigInteger value) {
|
||||
if (null == value)
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
if (0 > value.compareTo(BigInteger.ZERO))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
if (0 < value.compareTo(MAX_BIG_VALUE))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
this.value = value;
|
||||
this.top = this.value.shiftRight(32).and(new BigInteger("4294967295")).longValue();
|
||||
this.bottom = this.value.and(new BigInteger("4294967295")).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UInt64 from a String.
|
||||
*
|
||||
* @param value Must parse to a valid integer within MIN_VALUE–MAX_BIG_VALUE
|
||||
* @throws NumberFormatException if value is not an integer between MIN_VALUE and MAX_BIG_VALUE
|
||||
*/
|
||||
public UInt64(String value) {
|
||||
if (null == value)
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
BigInteger a = new BigInteger(value);
|
||||
if (0 > a.compareTo(BigInteger.ZERO))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
if (0 < a.compareTo(MAX_BIG_VALUE))
|
||||
throw new NumberFormatException(MessageFormat.format(getString("isNotBetween"), new Object[]{value, MIN_VALUE, MAX_BIG_VALUE}));
|
||||
this.value = a;
|
||||
this.top = this.value.shiftRight(32).and(new BigInteger("4294967295")).longValue();
|
||||
this.bottom = this.value.and(new BigInteger("4294967295")).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a BigInteger.
|
||||
*/
|
||||
public BigInteger value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a byte.
|
||||
*/
|
||||
public byte byteValue() {
|
||||
return value.byteValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a double.
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return value.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a float.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return value.floatValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a int.
|
||||
*/
|
||||
public int intValue() {
|
||||
return value.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a long.
|
||||
*/
|
||||
public long longValue() {
|
||||
return value.longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a short.
|
||||
*/
|
||||
public short shortValue() {
|
||||
return value.shortValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two UInt64s for equality.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof UInt64 && this.value.equals(((UInt64) o).value);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two UInt32s.
|
||||
*
|
||||
* @return 0 if equal, -ve or +ve if they are different.
|
||||
*/
|
||||
public int compareTo(UInt64 other) {
|
||||
return this.value.compareTo(other.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this as a string.
|
||||
*/
|
||||
public String toString() {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Most significant 4 bytes.
|
||||
*/
|
||||
public long top() {
|
||||
return top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Least significant 4 bytes.
|
||||
*/
|
||||
public long bottom() {
|
||||
return bottom;
|
||||
}
|
||||
}
|
||||
|
136
federation/sssd/src/main/java/org/freedesktop/dbus/Variant.java
Normal file
136
federation/sssd/src/main/java/org/freedesktop/dbus/Variant.java
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus;
|
||||
|
||||
import cx.ath.matthew.debug.Debug;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
/**
|
||||
* A Wrapper class for Variant values.
|
||||
* A method on DBus can send or receive a Variant.
|
||||
* This will wrap another value whose type is determined at runtime.
|
||||
* The Variant may be parameterized to restrict the types it may accept.
|
||||
*/
|
||||
public class Variant<T> {
|
||||
private final T o;
|
||||
private final Type type;
|
||||
private final String sig;
|
||||
|
||||
/**
|
||||
* Create a Variant from a basic type object.
|
||||
*
|
||||
* @param o The wrapped value.
|
||||
* @throws IllegalArugmentException If you try and wrap Null or an object of a non-basic type.
|
||||
*/
|
||||
public Variant(T o) throws IllegalArgumentException {
|
||||
if (null == o) throw new IllegalArgumentException(getString("cannotWrapNullInVariant"));
|
||||
type = o.getClass();
|
||||
try {
|
||||
String[] ss = Marshalling.getDBusType(o.getClass(), true);
|
||||
if (ss.length != 1)
|
||||
throw new IllegalArgumentException(getString("cannotWrapMultiValuedInVariant") + type);
|
||||
this.sig = ss[0];
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
throw new IllegalArgumentException(MessageFormat.format(getString("cannotWrapUnqualifiedVariant"), new Object[]{o.getClass(), DBe.getMessage()}));
|
||||
}
|
||||
this.o = o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Variant.
|
||||
*
|
||||
* @param o The wrapped value.
|
||||
* @param type The explicit type of the value.
|
||||
* @throws IllegalArugmentException If you try and wrap Null or an object which cannot be sent over DBus.
|
||||
*/
|
||||
public Variant(T o, Type type) throws IllegalArgumentException {
|
||||
if (null == o) throw new IllegalArgumentException(getString("cannotWrapNullInVariant"));
|
||||
this.type = type;
|
||||
try {
|
||||
String[] ss = Marshalling.getDBusType(type);
|
||||
if (ss.length != 1)
|
||||
throw new IllegalArgumentException(getString("cannotWrapMultiValuedInVariant") + type);
|
||||
this.sig = ss[0];
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
throw new IllegalArgumentException(MessageFormat.format(getString("cannotWrapUnqualifiedVariant"), new Object[]{type, DBe.getMessage()}));
|
||||
}
|
||||
this.o = o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Variant.
|
||||
*
|
||||
* @param o The wrapped value.
|
||||
* @param sig The explicit type of the value, as a dbus type string.
|
||||
* @throws IllegalArugmentException If you try and wrap Null or an object which cannot be sent over DBus.
|
||||
*/
|
||||
public Variant(T o, String sig) throws IllegalArgumentException {
|
||||
if (null == o) throw new IllegalArgumentException(getString("cannotWrapNullInVariant"));
|
||||
this.sig = sig;
|
||||
try {
|
||||
Vector<Type> ts = new Vector<Type>();
|
||||
Marshalling.getJavaType(sig, ts, 1);
|
||||
if (ts.size() != 1)
|
||||
throw new IllegalArgumentException(getString("cannotWrapNoTypesInVariant") + sig);
|
||||
this.type = ts.get(0);
|
||||
} catch (DBusException DBe) {
|
||||
if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
|
||||
throw new IllegalArgumentException(MessageFormat.format(getString("cannotWrapUnqualifiedVariant"), new Object[]{sig, DBe.getMessage()}));
|
||||
}
|
||||
this.o = o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the wrapped value.
|
||||
*/
|
||||
public T getValue() {
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the wrapped value.
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dbus signature of the wrapped value.
|
||||
*/
|
||||
public String getSig() {
|
||||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the Variant as a string.
|
||||
*/
|
||||
public String toString() {
|
||||
return "[" + o + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare this Variant with another by comparing contents
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean equals(Object other) {
|
||||
if (null == other) return false;
|
||||
if (!(other instanceof Variant)) return false;
|
||||
return this.o.equals(((Variant<? extends Object>) other).o);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
/**
|
||||
* An exception within DBus.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DBusException extends Exception {
|
||||
/**
|
||||
* Create an exception with the specified message
|
||||
*/
|
||||
public DBusException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
/**
|
||||
* An exception while running a remote method within DBus.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DBusExecutionException extends RuntimeException {
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Create an exception with the specified message
|
||||
*/
|
||||
public DBusExecutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DBus type of this exception. Use if this
|
||||
* was an exception we don't have a class file for.
|
||||
*/
|
||||
public String getType() {
|
||||
if (null == type) return getClass().getName();
|
||||
else return type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class FatalDBusException extends DBusException implements FatalException {
|
||||
public FatalDBusException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
public interface FatalException {
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class InternalMessageException extends DBusExecutionException implements NonFatalException {
|
||||
public InternalMessageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MarshallingException extends DBusException implements NonFatalException {
|
||||
public MarshallingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown if a message is formatted incorrectly.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageFormatException extends DBusException implements NonFatalException {
|
||||
public MessageFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageProtocolVersionException extends IOException implements FatalException {
|
||||
public MessageProtocolVersionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageTypeException extends IOException implements NonFatalException {
|
||||
public MessageTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
public interface NonFatalException {
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown if a DBus action is called when not connected to the Bus.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NotConnected extends DBusExecutionException implements FatalException {
|
||||
public NotConnected(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.exceptions;
|
||||
|
||||
import static org.freedesktop.dbus.Gettext.getString;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class UnknownTypeCodeException extends DBusException implements NonFatalException {
|
||||
public UnknownTypeCodeException(byte code) {
|
||||
super(getString("invalidDBusCode") + code);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.types;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type of a list.
|
||||
* Should be used whenever you need a Type variable for a list.
|
||||
*/
|
||||
public class DBusListType implements ParameterizedType {
|
||||
private Type v;
|
||||
|
||||
/**
|
||||
* Create a List type.
|
||||
*
|
||||
* @param v Type of the list contents.
|
||||
*/
|
||||
public DBusListType(Type v) {
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
public Type[] getActualTypeArguments() {
|
||||
return new Type[]{v};
|
||||
}
|
||||
|
||||
public Type getRawType() {
|
||||
return List.class;
|
||||
}
|
||||
|
||||
public Type getOwnerType() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.types;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The type of a map.
|
||||
* Should be used whenever you need a Type variable for a map.
|
||||
*/
|
||||
public class DBusMapType implements ParameterizedType {
|
||||
private Type k;
|
||||
private Type v;
|
||||
|
||||
/**
|
||||
* Create a map type.
|
||||
*
|
||||
* @param k The type of the keys.
|
||||
* @param v The type of the values.
|
||||
*/
|
||||
public DBusMapType(Type k, Type v) {
|
||||
this.k = k;
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
public Type[] getActualTypeArguments() {
|
||||
return new Type[]{k, v};
|
||||
}
|
||||
|
||||
public Type getRawType() {
|
||||
return Map.class;
|
||||
}
|
||||
|
||||
public Type getOwnerType() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
D-Bus Java Implementation
|
||||
Copyright (c) 2005-2006 Matthew Johnson
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License Version 2 or the
|
||||
Academic Free Licence Version 2.1.
|
||||
|
||||
Full licence texts are included in the COPYING file with this program.
|
||||
*/
|
||||
package org.freedesktop.dbus.types;
|
||||
|
||||
import org.freedesktop.dbus.Struct;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* The type of a struct.
|
||||
* Should be used whenever you need a Type variable for a struct.
|
||||
*/
|
||||
public class DBusStructType implements ParameterizedType {
|
||||
private Type[] contents;
|
||||
|
||||
/**
|
||||
* Create a struct type.
|
||||
*
|
||||
* @param contents The types contained in this struct.
|
||||
*/
|
||||
public DBusStructType(Type... contents) {
|
||||
this.contents = contents;
|
||||
}
|
||||
|
||||
public Type[] getActualTypeArguments() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
public Type getRawType() {
|
||||
return Struct.class;
|
||||
}
|
||||
|
||||
public Type getOwnerType() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.freedesktop.sssd.infopipe;
|
||||
|
||||
import org.freedesktop.dbus.DBusInterface;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
public interface Cache extends DBusInterface {
|
||||
|
||||
List<DBusInterface> List();
|
||||
|
||||
List<DBusInterface> ListByDomain(String domain_name);
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.freedesktop.sssd.infopipe;
|
||||
|
||||
import org.freedesktop.dbus.DBusInterface;
|
||||
import org.freedesktop.dbus.DBusInterfaceName;
|
||||
import org.freedesktop.dbus.DBusMemberName;
|
||||
import org.freedesktop.dbus.Variant;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
@DBusInterfaceName("org.freedesktop.sssd.infopipe")
|
||||
public interface InfoPipe extends DBusInterface {
|
||||
|
||||
String OBJECTPATH = "/org/freedesktop/sssd/infopipe";
|
||||
|
||||
@DBusMemberName("GetUserAttr")
|
||||
Map<String, Variant> getUserAttributes(String user, List<String> attr);
|
||||
|
||||
@DBusMemberName("GetUserGroups")
|
||||
List<String> getUserGroups(String user);
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.freedesktop.sssd.infopipe;
|
||||
|
||||
import org.freedesktop.dbus.DBusInterface;
|
||||
import org.freedesktop.dbus.DBusInterfaceName;
|
||||
import org.freedesktop.dbus.DBusMemberName;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
@DBusInterfaceName("org.freedesktop.sssd.infopipe.Users")
|
||||
public interface User extends DBusInterface {
|
||||
|
||||
String OBJECTPATH = "/org/freedesktop/sssd/infopipe/Users";
|
||||
|
||||
@DBusMemberName("FindByCertificate")
|
||||
DBusInterface findByCertificate(String pem_cert);
|
||||
|
||||
}
|
188
federation/sssd/src/main/java/org/jvnet/libpam/PAM.java
Normal file
188
federation/sssd/src/main/java/org/jvnet/libpam/PAM.java
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jvnet.libpam;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
import org.jvnet.libpam.impl.PAMLibrary.pam_conv;
|
||||
import org.jvnet.libpam.impl.PAMLibrary.pam_conv.PamCallback;
|
||||
import org.jvnet.libpam.impl.PAMLibrary.pam_handle_t;
|
||||
import org.jvnet.libpam.impl.PAMLibrary.pam_message;
|
||||
import org.jvnet.libpam.impl.PAMLibrary.pam_response;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static com.sun.jna.Native.POINTER_SIZE;
|
||||
import static org.jvnet.libpam.impl.CLibrary.libc;
|
||||
import static org.jvnet.libpam.impl.PAMLibrary.PAM_CONV_ERR;
|
||||
import static org.jvnet.libpam.impl.PAMLibrary.PAM_PROMPT_ECHO_OFF;
|
||||
import static org.jvnet.libpam.impl.PAMLibrary.PAM_SUCCESS;
|
||||
import static org.jvnet.libpam.impl.PAMLibrary.PAM_USER;
|
||||
import static org.jvnet.libpam.impl.PAMLibrary.libpam;
|
||||
|
||||
/**
|
||||
* PAM authenticator.
|
||||
* <p>
|
||||
* <p>
|
||||
* Instances are thread unsafe and non reentrant. An instace cannot be reused
|
||||
* to authenticate multiple users.
|
||||
* <p>
|
||||
* <p>
|
||||
* For an overview of PAM programming, refer to the following resources:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li><a href="http://www.netbsd.org/docs/guide/en/chap-pam.html">NetBSD PAM programming guide</a>
|
||||
* <li><a href="http://www.kernel.org/pub/linux/libs/pam/">Linux PAM</a>
|
||||
* </ul>
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class PAM {
|
||||
private pam_handle_t pht;
|
||||
private int ret;
|
||||
|
||||
/**
|
||||
* Temporarily stored to pass a value from {@link #authenticate(String, String...)}
|
||||
* to {@link pam_conv}.
|
||||
*/
|
||||
private String[] factors;
|
||||
|
||||
/**
|
||||
* Creates a new authenticator.
|
||||
*
|
||||
* @param serviceName PAM service name. This corresponds to the service name that shows up
|
||||
* in the PAM configuration,
|
||||
*/
|
||||
public PAM(String serviceName) throws PAMException {
|
||||
pam_conv conv = new pam_conv(new PamCallback() {
|
||||
public int callback(int num_msg, Pointer msg, Pointer resp, Pointer _) {
|
||||
LOGGER.debug("pam_conv num_msg=" + num_msg);
|
||||
if (factors == null)
|
||||
return PAM_CONV_ERR;
|
||||
|
||||
// allocates pam_response[num_msg]. the caller will free this
|
||||
Pointer m = libc.calloc(pam_response.SIZE, num_msg);
|
||||
resp.setPointer(0, m);
|
||||
|
||||
for (int i = 0; i < factors.length; i++) {
|
||||
pam_message pm = new pam_message(msg.getPointer(POINTER_SIZE * i));
|
||||
LOGGER.debug(pm.msg_style + ":" + pm.msg);
|
||||
if (pm.msg_style == PAM_PROMPT_ECHO_OFF) {
|
||||
pam_response r = new pam_response(m.share(pam_response.SIZE * i));
|
||||
r.setResp(factors[i]);
|
||||
r.write(); // write to (*resp)[i]
|
||||
}
|
||||
}
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
});
|
||||
|
||||
PointerByReference phtr = new PointerByReference();
|
||||
check(libpam.pam_start(serviceName, null, conv, phtr), "pam_start failed");
|
||||
pht = new pam_handle_t(phtr.getValue());
|
||||
}
|
||||
|
||||
private void check(int ret, String msg) throws PAMException {
|
||||
this.ret = ret;
|
||||
if (ret != 0) {
|
||||
if (pht != null)
|
||||
throw new PAMException(msg + " : " + libpam.pam_strerror(pht, ret));
|
||||
else
|
||||
throw new PAMException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user with a password.
|
||||
*
|
||||
* @return Upon a successful authentication, return information about the user.
|
||||
* @throws PAMException If the authentication fails.
|
||||
*/
|
||||
public UnixUser authenticate(String username, String... factors) throws PAMException {
|
||||
this.factors = factors;
|
||||
try {
|
||||
check(libpam.pam_set_item(pht, PAM_USER, username), "pam_set_item failed");
|
||||
check(libpam.pam_authenticate(pht, 0), "pam_authenticate failed");
|
||||
check(libpam.pam_setcred(pht, 0), "pam_setcred failed");
|
||||
// several different error code seem to be used to represent authentication failures
|
||||
// check(libpam.pam_acct_mgmt(pht,0),"pam_acct_mgmt failed");
|
||||
|
||||
PointerByReference r = new PointerByReference();
|
||||
check(libpam.pam_get_item(pht, PAM_USER, r), "pam_get_item failed");
|
||||
String userName = r.getValue().getString(0);
|
||||
passwd pwd = libc.getpwnam(userName);
|
||||
if (pwd == null)
|
||||
throw new PAMException("Authentication succeeded but no user information is available");
|
||||
return new UnixUser(userName, pwd);
|
||||
} finally {
|
||||
this.factors = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the groups a user belongs to
|
||||
*
|
||||
* @param username
|
||||
* @return Set of group names
|
||||
* @throws PAMException
|
||||
* @deprecated Pointless and ugly convenience method.
|
||||
*/
|
||||
public Set<String> getGroupsOfUser(String username) throws PAMException {
|
||||
return new UnixUser(username).getGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* After a successful authentication, call this method to obtain the effective user name.
|
||||
* This can be different from the user name that you passed to the {@link #authenticate(String, String)}
|
||||
* method.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs an early disposal of the object, instead of letting this GC-ed.
|
||||
* Since PAM may hold on to native resources that don't put pressure on Java GC,
|
||||
* doing this is a good idea.
|
||||
* <p>
|
||||
* <p>
|
||||
* This method is called by {@link #finalize()}, too, so it's not required
|
||||
* to call this method explicitly, however.
|
||||
*/
|
||||
public void dispose() {
|
||||
if (pht != null) {
|
||||
libpam.pam_end(pht, ret);
|
||||
pht = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
dispose();
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(PAM.class.getName());
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jvnet.libpam;
|
||||
|
||||
/**
|
||||
* Exception in PAM invoactions.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class PAMException extends Exception {
|
||||
public PAMException() {
|
||||
}
|
||||
|
||||
public PAMException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PAMException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public PAMException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
159
federation/sssd/src/main/java/org/jvnet/libpam/UnixUser.java
Normal file
159
federation/sssd/src/main/java/org/jvnet/libpam/UnixUser.java
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jvnet.libpam;
|
||||
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import org.jvnet.libpam.impl.CLibrary.group;
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jvnet.libpam.impl.CLibrary.libc;
|
||||
|
||||
/**
|
||||
* Represents an Unix user. Immutable.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class UnixUser {
|
||||
private final String userName, gecos, dir, shell;
|
||||
private final int uid, gid;
|
||||
private final Set<String> groups;
|
||||
|
||||
/*package*/ UnixUser(String userName, passwd pwd) throws PAMException {
|
||||
this.userName = userName;
|
||||
this.gecos = pwd.getPwGecos();
|
||||
this.dir = pwd.getPwDir();
|
||||
this.shell = pwd.getPwShell();
|
||||
this.uid = pwd.getPwUid();
|
||||
this.gid = pwd.getPwGid();
|
||||
|
||||
int sz = 4; /*sizeof(gid_t)*/
|
||||
|
||||
int ngroups = 64;
|
||||
Memory m = new Memory(ngroups * sz);
|
||||
IntByReference pngroups = new IntByReference(ngroups);
|
||||
try {
|
||||
if (libc.getgrouplist(userName, pwd.getPwGid(), m, pngroups) < 0) {
|
||||
// allocate a bigger memory
|
||||
m = new Memory(pngroups.getValue() * sz);
|
||||
if (libc.getgrouplist(userName, pwd.getPwGid(), m, pngroups) < 0)
|
||||
// shouldn't happen, but just in case.
|
||||
throw new PAMException("getgrouplist failed");
|
||||
}
|
||||
ngroups = pngroups.getValue();
|
||||
} catch (LinkageError e) {
|
||||
// some platform, notably Solaris, doesn't have the getgrouplist function
|
||||
ngroups = libc._getgroupsbymember(userName, m, ngroups, 0);
|
||||
if (ngroups < 0)
|
||||
throw new PAMException("_getgroupsbymember failed");
|
||||
}
|
||||
|
||||
groups = new HashSet<String>();
|
||||
for (int i = 0; i < ngroups; i++) {
|
||||
int gid = m.getInt(i * sz);
|
||||
group grp = libc.getgrgid(gid);
|
||||
if (grp == null) {
|
||||
continue;
|
||||
}
|
||||
groups.add(grp.gr_name);
|
||||
}
|
||||
}
|
||||
|
||||
public UnixUser(String userName) throws PAMException {
|
||||
this(userName, passwd.loadPasswd(userName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor for mocking. Not intended for regular use. Only for testing.
|
||||
* This signature may change in the future.
|
||||
*/
|
||||
protected UnixUser(String userName, String gecos, String dir, String shell, int uid, int gid, Set<String> groups) {
|
||||
this.userName = userName;
|
||||
this.gecos = gecos;
|
||||
this.dir = dir;
|
||||
this.shell = shell;
|
||||
this.uid = uid;
|
||||
this.gid = gid;
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unix account name. Never null.
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UID of this user.
|
||||
*/
|
||||
public int getUID() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GID of this user.
|
||||
*/
|
||||
public int getGID() {
|
||||
return gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the gecos (the real name) of this user.
|
||||
*/
|
||||
public String getGecos() {
|
||||
return gecos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the home directory of this user.
|
||||
*/
|
||||
public String getDir() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shell of this user.
|
||||
*/
|
||||
public String getShell() {
|
||||
return shell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the groups that this user belongs to.
|
||||
*
|
||||
* @return never null.
|
||||
*/
|
||||
public Set<String> getGroups() {
|
||||
return Collections.unmodifiableSet(groups);
|
||||
}
|
||||
|
||||
public static boolean exists(String name) {
|
||||
return libc.getpwnam(name) != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2011, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
/**
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface BSDCLibrary extends CLibrary {
|
||||
|
||||
BSDPasswd getpwnam(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2011, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FreeeBSD, OpenBSD and MacOS passwd
|
||||
* <p>
|
||||
* struct passwd {
|
||||
* char *pw_name;
|
||||
* char *pw_passwd;
|
||||
* uid_t pw_uid;
|
||||
* gid_t pw_gid;
|
||||
* time_t pw_change;
|
||||
* char *pw_class;
|
||||
* char *pw_gecos;
|
||||
* char *pw_dir;
|
||||
* char *pw_shell;
|
||||
* time_t pw_expire;
|
||||
* };
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class BSDPasswd extends passwd {
|
||||
/* password change time */
|
||||
public long pw_change;
|
||||
|
||||
/* user access class */
|
||||
public String pw_class;
|
||||
|
||||
/* Honeywell login info */
|
||||
public String pw_gecos;
|
||||
|
||||
/* home directory */
|
||||
public String pw_dir;
|
||||
|
||||
/* default shell */
|
||||
public String pw_shell;
|
||||
|
||||
/* account expiration */
|
||||
public long pw_expire;
|
||||
|
||||
@Override
|
||||
public String getPwGecos() {
|
||||
return pw_gecos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwDir() {
|
||||
return pw_dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwShell() {
|
||||
return pw_shell;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
List fieldOrder = new ArrayList(super.getFieldOrder());
|
||||
fieldOrder.addAll(Arrays.asList("pw_change", "pw_class", "pw_gecos",
|
||||
"pw_dir", "pw_shell", "pw_expire"));
|
||||
return fieldOrder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Platform;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import org.jvnet.libpam.PAMException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface CLibrary extends Library {
|
||||
/**
|
||||
* Comparing http://linux.die.net/man/3/getpwnam
|
||||
* and my Mac OS X reveals that the structure of this field isn't very portable.
|
||||
* In particular, we cannot read the real name reliably.
|
||||
*/
|
||||
public class passwd extends Structure {
|
||||
/**
|
||||
* User name.
|
||||
*/
|
||||
public String pw_name;
|
||||
/**
|
||||
* Encrypted password.
|
||||
*/
|
||||
public String pw_passwd;
|
||||
public int pw_uid;
|
||||
public int pw_gid;
|
||||
|
||||
// ... there are a lot more fields
|
||||
|
||||
public static passwd loadPasswd(String userName) throws PAMException {
|
||||
passwd pwd = libc.getpwnam(userName);
|
||||
if (pwd == null) {
|
||||
throw new PAMException("No user information is available");
|
||||
}
|
||||
return pwd;
|
||||
}
|
||||
|
||||
public String getPwName() {
|
||||
return pw_name;
|
||||
}
|
||||
|
||||
public String getPwPasswd() {
|
||||
return pw_passwd;
|
||||
}
|
||||
|
||||
public int getPwUid() {
|
||||
return pw_uid;
|
||||
}
|
||||
|
||||
public int getPwGid() {
|
||||
return pw_gid;
|
||||
}
|
||||
|
||||
public String getPwGecos() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPwDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPwShell() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("pw_name", "pw_passwd", "pw_uid", "pw_gid");
|
||||
}
|
||||
}
|
||||
|
||||
public class group extends Structure {
|
||||
public String gr_name;
|
||||
// ... the rest of the field is not interesting for us
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("gr_name");
|
||||
}
|
||||
}
|
||||
|
||||
Pointer calloc(int count, int size);
|
||||
|
||||
Pointer strdup(String s);
|
||||
|
||||
passwd getpwnam(String username);
|
||||
|
||||
/**
|
||||
* Lists up group IDs of the given user. On Linux and most BSDs, but not on Solaris.
|
||||
* See http://www.gnu.org/software/hello/manual/gnulib/getgrouplist.html
|
||||
*/
|
||||
int getgrouplist(String user, int/*gid_t*/ group, Memory groups, IntByReference ngroups);
|
||||
|
||||
/**
|
||||
* getgrouplist equivalent on Solaris.
|
||||
* See http://mail.opensolaris.org/pipermail/sparks-discuss/2008-September/000528.html
|
||||
*/
|
||||
int _getgroupsbymember(String user, Memory groups, int maxgids, int numgids);
|
||||
|
||||
group getgrgid(int/*gid_t*/ gid);
|
||||
|
||||
group getgrnam(String name);
|
||||
|
||||
// other user/group related functions that are likely useful
|
||||
// see http://www.gnu.org/software/libc/manual/html_node/Users-and-Groups.html#Users-and-Groups
|
||||
|
||||
|
||||
public static final CLibrary libc = Instance.init();
|
||||
|
||||
static class Instance {
|
||||
private static CLibrary init() {
|
||||
if (Platform.isMac() || Platform.isOpenBSD()) {
|
||||
return (CLibrary) Native.loadLibrary("c", BSDCLibrary.class);
|
||||
} else if (Platform.isFreeBSD()) {
|
||||
return (CLibrary) Native.loadLibrary("c", FreeBSDCLibrary.class);
|
||||
} else if (Platform.isSolaris()) {
|
||||
return (CLibrary) Native.loadLibrary("c", SolarisCLibrary.class);
|
||||
} else if (Platform.isLinux()) {
|
||||
return (CLibrary) Native.loadLibrary("c", LinuxCLibrary.class);
|
||||
} else {
|
||||
return (CLibrary) Native.loadLibrary("c", CLibrary.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2014, R. Tyler Croy, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
/**
|
||||
* @author R. Tyler Croy
|
||||
*/
|
||||
public interface FreeBSDCLibrary extends CLibrary {
|
||||
|
||||
FreeBSDPasswd getpwnam(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2014, R. Tyler Croy, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FreeeBSD
|
||||
* <p>
|
||||
* struct passwd {
|
||||
* char *pw_name;
|
||||
* char *pw_passwd;
|
||||
* uid_t pw_uid;
|
||||
* gid_t pw_gid;
|
||||
* time_t pw_change;
|
||||
* char *pw_class;
|
||||
* char *pw_gecos;
|
||||
* char *pw_dir;
|
||||
* char *pw_shell;
|
||||
* time_t pw_expire;
|
||||
* int pw_fields;
|
||||
* };
|
||||
*
|
||||
* @author R. Tyler Croy
|
||||
*/
|
||||
|
||||
public class FreeBSDPasswd extends passwd {
|
||||
/* password change time */
|
||||
public long pw_change;
|
||||
|
||||
/* user access class */
|
||||
public String pw_class;
|
||||
|
||||
/* Honeywell login info */
|
||||
public String pw_gecos;
|
||||
|
||||
/* home directory */
|
||||
public String pw_dir;
|
||||
|
||||
/* default shell */
|
||||
public String pw_shell;
|
||||
|
||||
/* account expiration */
|
||||
public long pw_expire;
|
||||
|
||||
/* internal on FreeBSD? */
|
||||
public int pw_fields;
|
||||
|
||||
@Override
|
||||
public String getPwGecos() {
|
||||
return pw_gecos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwDir() {
|
||||
return pw_dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwShell() {
|
||||
return pw_shell;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
List fieldOrder = new ArrayList(super.getFieldOrder());
|
||||
fieldOrder.addAll(Arrays.asList("pw_change", "pw_class", "pw_gecos",
|
||||
"pw_dir", "pw_shell", "pw_expire", "pw_fields"));
|
||||
return fieldOrder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2011, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
/**
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface LinuxCLibrary extends CLibrary {
|
||||
|
||||
LinuxPasswd getpwnam(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2011, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Linux passwd
|
||||
* <p>
|
||||
* ?struct passwd
|
||||
* {
|
||||
* char *pw_name;
|
||||
* char *pw_passwd;
|
||||
* __uid_t pw_uid;
|
||||
* __gid_t pw_gid;
|
||||
* char *pw_gecos;
|
||||
* char *pw_dir;
|
||||
* char *pw_shell;
|
||||
* };
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class LinuxPasswd extends passwd {
|
||||
/* Honeywell login info */
|
||||
public String pw_gecos;
|
||||
|
||||
/* home directory */
|
||||
public String pw_dir;
|
||||
|
||||
/* default shell */
|
||||
public String pw_shell;
|
||||
|
||||
|
||||
public String getPwGecos() {
|
||||
return pw_gecos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwDir() {
|
||||
return pw_dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwShell() {
|
||||
return pw_shell;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
List fieldOrder = new ArrayList(super.getFieldOrder());
|
||||
fieldOrder.addAll(Arrays.asList("pw_gecos", "pw_dir", "pw_shell"));
|
||||
return fieldOrder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import com.sun.jna.Callback;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.PointerType;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jvnet.libpam.impl.CLibrary.libc;
|
||||
|
||||
/**
|
||||
* libpam.so binding.
|
||||
* <p>
|
||||
* See http://www.opengroup.org/onlinepubs/008329799/apdxa.htm
|
||||
* for the online reference of pam_appl.h
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface PAMLibrary extends Library {
|
||||
class pam_handle_t extends PointerType {
|
||||
public pam_handle_t() {
|
||||
}
|
||||
|
||||
public pam_handle_t(Pointer pointer) {
|
||||
super(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
class pam_message extends Structure {
|
||||
public int msg_style;
|
||||
public String msg;
|
||||
|
||||
/**
|
||||
* Attach to the memory region pointed by the given pointer.
|
||||
*/
|
||||
public pam_message(Pointer src) {
|
||||
useMemory(src);
|
||||
read();
|
||||
}
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("msg_style", "msg");
|
||||
}
|
||||
}
|
||||
|
||||
class pam_response extends Structure {
|
||||
/**
|
||||
* This is really a string, but this field needs to be malloc-ed by the conversation
|
||||
* method, and to be freed by the caler, so I bind it to {@link Pointer} here.
|
||||
* <p>
|
||||
* The man page doesn't say that, but see
|
||||
* http://www.netbsd.org/docs/guide/en/chap-pam.html#pam-sample-conv
|
||||
* This behavior is confirmed with a test, too; if I don't do strdup,
|
||||
* libpam crashes.
|
||||
*/
|
||||
public Pointer resp;
|
||||
public int resp_retcode;
|
||||
|
||||
/**
|
||||
* Attach to the memory region pointed by the given memory.
|
||||
*/
|
||||
public pam_response(Pointer src) {
|
||||
useMemory(src);
|
||||
read();
|
||||
}
|
||||
|
||||
public pam_response() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the response code.
|
||||
*/
|
||||
public void setResp(String msg) {
|
||||
this.resp = libc.strdup(msg);
|
||||
}
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("resp", "resp_retcode");
|
||||
}
|
||||
|
||||
public static final int SIZE = new pam_response().size();
|
||||
}
|
||||
|
||||
class pam_conv extends Structure {
|
||||
public interface PamCallback extends Callback {
|
||||
/**
|
||||
* According to http://www.netbsd.org/docs/guide/en/chap-pam.html#pam-sample-conv,
|
||||
* resp and its member string both needs to be allocated by malloc,
|
||||
* to be freed by the caller.
|
||||
*/
|
||||
int callback(int num_msg, Pointer msg, Pointer resp, Pointer _);
|
||||
}
|
||||
|
||||
public PamCallback conv;
|
||||
public Pointer _;
|
||||
|
||||
public pam_conv(PamCallback conv) {
|
||||
this.conv = conv;
|
||||
}
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("conv", "_");
|
||||
}
|
||||
}
|
||||
|
||||
int pam_start(String service, String user, pam_conv conv, PointerByReference/* pam_handle_t** */ pamh_p);
|
||||
|
||||
int pam_end(pam_handle_t handle, int pam_status);
|
||||
|
||||
int pam_set_item(pam_handle_t handle, int item_type, String item);
|
||||
|
||||
int pam_get_item(pam_handle_t handle, int item_type, PointerByReference item);
|
||||
|
||||
int pam_authenticate(pam_handle_t handle, int flags);
|
||||
|
||||
int pam_setcred(pam_handle_t handle, int flags);
|
||||
|
||||
int pam_acct_mgmt(pam_handle_t handle, int flags);
|
||||
|
||||
String pam_strerror(pam_handle_t handle, int pam_error);
|
||||
|
||||
final int PAM_USER = 2;
|
||||
|
||||
// error code
|
||||
final int PAM_SUCCESS = 0;
|
||||
final int PAM_CONV_ERR = 6;
|
||||
|
||||
|
||||
final int PAM_PROMPT_ECHO_OFF = 1; /* Echo off when getting response */
|
||||
final int PAM_PROMPT_ECHO_ON = 2; /* Echo on when getting response */
|
||||
final int PAM_ERROR_MSG = 3; /* Error message */
|
||||
final int PAM_TEXT_INFO = 4; /* Textual information */
|
||||
|
||||
public static final PAMLibrary libpam = (PAMLibrary) Native.loadLibrary("pam", PAMLibrary.class);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
/**
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface SolarisCLibrary extends CLibrary {
|
||||
|
||||
SolarisPasswd getpwnam(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package org.jvnet.libpam.impl;
|
||||
|
||||
import org.jvnet.libpam.impl.CLibrary.passwd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Solaris passwd
|
||||
* <p>
|
||||
* struct passwd {
|
||||
* char *pw_name;
|
||||
* char *pw_passwd;
|
||||
* uid_t pw_uid;
|
||||
* gid_t pw_gid;
|
||||
* char *pw_age;
|
||||
* char *pw_comment;
|
||||
* char *pw_gecos;
|
||||
* char *pw_dir;
|
||||
* char *pw_shell;
|
||||
* };
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SolarisPasswd extends passwd {
|
||||
public String pw_age;
|
||||
|
||||
public String pw_comment;
|
||||
|
||||
public String pw_gecos;
|
||||
|
||||
public String pw_dir;
|
||||
|
||||
public String pw_shell;
|
||||
|
||||
|
||||
@Override
|
||||
public String getPwGecos() {
|
||||
return pw_gecos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwDir() {
|
||||
return pw_dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPwShell() {
|
||||
return pw_shell;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
List fieldOrder = new ArrayList(super.getFieldOrder());
|
||||
fieldOrder.addAll(Arrays.asList("pw_age", "pw_comment", "pw_gecos",
|
||||
"pw_dir", "pw_shell"));
|
||||
return fieldOrder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.keycloak.federation.sssd;
|
||||
|
||||
import org.keycloak.models.ModelReadOnlyException;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
|
||||
/**
|
||||
* Readonly proxy for a SSSD UserModel that prevents attributes from being updated.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ReadonlySSSDUserModelDelegate extends UserModelDelegate implements UserModel {
|
||||
|
||||
private final SSSDFederationProvider provider;
|
||||
|
||||
public ReadonlySSSDUserModelDelegate(UserModel delegate, SSSDFederationProvider provider) {
|
||||
super(delegate);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new ModelReadOnlyException("Federated storage is not writable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
throw new ModelReadOnlyException("Federated storage is not writable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String first) {
|
||||
throw new ModelReadOnlyException("Federated storage is not writable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Federated storage is not writable");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (provider.getSupportedCredentialTypes(delegate).contains(cred.getType())) {
|
||||
throw new ModelReadOnlyException("Federated storage is not writable");
|
||||
}
|
||||
delegate.updateCredential(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
throw new ModelReadOnlyException("Federated storage is not writable");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.keycloak.federation.sssd;
|
||||
|
||||
import org.freedesktop.dbus.Variant;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.federation.sssd.api.Sssd;
|
||||
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.services.managers.UserManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* SPI provider implementation to retrieve data from SSSD and authenticate
|
||||
* against PAM
|
||||
*
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class SSSDFederationProvider implements UserFederationProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
|
||||
|
||||
protected static final Set<String> supportedCredentialTypes = new HashSet<>();
|
||||
private final SSSDFederationProviderFactory factory;
|
||||
protected KeycloakSession session;
|
||||
protected UserFederationProviderModel model;
|
||||
|
||||
public SSSDFederationProvider(KeycloakSession session, UserFederationProviderModel model, SSSDFederationProviderFactory sssdFederationProviderFactory) {
|
||||
this.session = session;
|
||||
this.model = model;
|
||||
this.factory = sssdFederationProviderFactory;
|
||||
}
|
||||
|
||||
static {
|
||||
supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(RealmModel realm, String username) {
|
||||
return findOrCreateAuthenticatedUser(realm, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after successful authentication
|
||||
*
|
||||
* @param realm realm
|
||||
* @param username username without realm prefix
|
||||
* @return user if found or successfully created. Null if user with same username already exists, but is not linked to this provider
|
||||
*/
|
||||
protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
|
||||
UserModel user = session.userStorage().getUserByUsername(username, realm);
|
||||
if (user != null) {
|
||||
logger.debug("SSSD authenticated user " + username + " found in Keycloak storage");
|
||||
|
||||
if (!model.getId().equals(user.getFederationLink())) {
|
||||
logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]");
|
||||
return null;
|
||||
} else {
|
||||
UserModel proxied = validateAndProxy(realm, user);
|
||||
if (proxied != null) {
|
||||
return proxied;
|
||||
} else {
|
||||
logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
|
||||
"] but principal is not correct.");
|
||||
logger.warn("Will re-create user");
|
||||
new UserManager(session).removeUser(realm, user, session.userStorage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("SSSD authenticated user " + username + " not in Keycloak storage. Creating...");
|
||||
return importUserToKeycloak(realm, username);
|
||||
}
|
||||
|
||||
protected UserModel importUserToKeycloak(RealmModel realm, String username) {
|
||||
Sssd sssd = new Sssd(username);
|
||||
Map<String, Variant> sssdUser = sssd.getUserAttributes();
|
||||
logger.debugf("Creating SSSD user: %s to local Keycloak storage", username);
|
||||
UserModel user = session.userStorage().addUser(realm, username);
|
||||
user.setEnabled(true);
|
||||
user.setEmail(Sssd.getRawAttribute(sssdUser.get("mail")));
|
||||
user.setFirstName(Sssd.getRawAttribute(sssdUser.get("givenname")));
|
||||
user.setLastName(Sssd.getRawAttribute(sssdUser.get("sn")));
|
||||
for (String s : sssd.getUserGroups()) {
|
||||
GroupModel group = KeycloakModelUtils.findGroupByPath(realm, "/" + s);
|
||||
if (group == null) {
|
||||
group = session.realms().createGroup(realm, s);
|
||||
}
|
||||
user.joinGroup(group);
|
||||
}
|
||||
user.setFederationLink(model.getId());
|
||||
return validateAndProxy(realm, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(RealmModel realm, String email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
// complete We don't care about the realm being removed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
// complete we dont'care if a role is removed
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
// complete we dont'care if a role is removed
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(RealmModel realm, UserModel local) {
|
||||
Map<String, Variant> attributes = new Sssd(local.getUsername()).getUserAttributes();
|
||||
return Sssd.getRawAttribute(attributes.get("mail")).equalsIgnoreCase(local.getEmail());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes(UserModel user) {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes() {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
PAMAuthenticator pam = factory.createPAMAuthenticator(user.getUsername(), cred.getValue());
|
||||
return (pam.authenticate() != null);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
return validCredentials(realm, user, Arrays.asList(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
|
||||
return CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel validateAndProxy(RealmModel realm, UserModel local) {
|
||||
if (isValid(realm, local)) {
|
||||
return new ReadonlySSSDUserModelDelegate(local, this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean synchronizeRegistrations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel register(RealmModel realm, UserModel user) {
|
||||
throw new IllegalStateException("Registration not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Sssd.disconnect();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.keycloak.federation.sssd;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderFactory;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserFederationSyncResult;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class SSSDFederationProviderFactory implements UserFederationProviderFactory {
|
||||
|
||||
private static final String PROVIDER_NAME = "sssd";
|
||||
private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
|
||||
|
||||
static final Set<String> configOptions = new HashSet<String>();
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
|
||||
return new SSSDFederationProvider(session, model, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the configuration options to render and display in the admin console's generic management page for this
|
||||
* plugin
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getConfigurationOptions() {
|
||||
return configOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
|
||||
logger.info("Sync users not supported for this provider");
|
||||
return UserFederationSyncResult.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
|
||||
logger.info("Sync users not supported for this provider");
|
||||
return UserFederationSyncResult.empty();
|
||||
}
|
||||
|
||||
protected PAMAuthenticator createPAMAuthenticator(String username, String... factors) {
|
||||
return new PAMAuthenticator(username, factors);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.keycloak.federation.sssd.api;
|
||||
|
||||
import org.freedesktop.dbus.DBusConnection;
|
||||
import org.freedesktop.dbus.Variant;
|
||||
import org.freedesktop.dbus.exceptions.DBusException;
|
||||
import org.freedesktop.sssd.infopipe.InfoPipe;
|
||||
import org.freedesktop.sssd.infopipe.User;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Sssd {
|
||||
|
||||
public static final String BUSNAME = "org.freedesktop.sssd.infopipe";
|
||||
|
||||
public static User user() {
|
||||
return SingletonHolder.USER_OBJECT;
|
||||
}
|
||||
|
||||
public static InfoPipe infopipe() {
|
||||
return SingletonHolder.INFOPIPE_OBJECT;
|
||||
}
|
||||
|
||||
public static void disconnect() {
|
||||
SingletonHolder.DBUS_CONNECTION.disconnect();
|
||||
}
|
||||
|
||||
private String username;
|
||||
private static final Logger logger = Logger.getLogger(Sssd.class);
|
||||
|
||||
private Sssd() {
|
||||
}
|
||||
|
||||
public Sssd(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static InfoPipe INFOPIPE_OBJECT;
|
||||
private static User USER_OBJECT;
|
||||
private static DBusConnection DBUS_CONNECTION;
|
||||
|
||||
static {
|
||||
try {
|
||||
DBUS_CONNECTION = DBusConnection.getConnection(DBusConnection.SYSTEM);
|
||||
INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class);
|
||||
USER_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, User.OBJECTPATH, User.class);
|
||||
} catch (DBusException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getRawAttribute(Variant variant) {
|
||||
if (variant != null) {
|
||||
Vector value = (Vector) variant.getValue();
|
||||
if (value.size() >= 1) {
|
||||
return value.get(0).toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Variant> getUserAttributes() {
|
||||
String[] attr = {"mail", "givenname", "sn", "telephoneNumber"};
|
||||
Map<String, Variant> attributes = null;
|
||||
try {
|
||||
InfoPipe infoPipe = infopipe();
|
||||
attributes = infoPipe.getUserAttributes(username, Arrays.asList(attr));
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to retrieve user's attributes from SSSD", e);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public List<String> getUserGroups() {
|
||||
List<String> userGroups = null;
|
||||
try {
|
||||
InfoPipe infoPipe = Sssd.infopipe();
|
||||
userGroups = infoPipe.getUserGroups(username);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to retrieve user's groups from SSSD", e);
|
||||
}
|
||||
return userGroups;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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.keycloak.federation.sssd.impl;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jvnet.libpam.PAM;
|
||||
import org.jvnet.libpam.PAMException;
|
||||
import org.jvnet.libpam.UnixUser;
|
||||
|
||||
/**
|
||||
* PAMAuthenticator for Unix users
|
||||
*
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class PAMAuthenticator {
|
||||
|
||||
private static final String PAM_SERVICE = "keycloak";
|
||||
private static final Logger logger = Logger.getLogger(PAMAuthenticator.class);
|
||||
private final String username;
|
||||
private final String[] factors;
|
||||
|
||||
public PAMAuthenticator(String username, String... factors) {
|
||||
this.username = username;
|
||||
this.factors = factors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if user was successfully authenticated against PAM
|
||||
*
|
||||
* @return UnixUser object if user was successfully authenticated
|
||||
*/
|
||||
public UnixUser authenticate() {
|
||||
PAM pam = null;
|
||||
UnixUser user = null;
|
||||
try {
|
||||
pam = new PAM(PAM_SERVICE);
|
||||
user = pam.authenticate(username, factors);
|
||||
} catch (PAMException e) {
|
||||
logger.error("Authentication failed", e);
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
pam.dispose();
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
37
federation/sssd/src/main/resources/DBUS-JAVA-AUTHORS
Normal file
37
federation/sssd/src/main/resources/DBUS-JAVA-AUTHORS
Normal file
|
@ -0,0 +1,37 @@
|
|||
The D-Bus Java implementation was written by:
|
||||
|
||||
Matthew Johnson <dbus -at matthew -dot- ath -dot- cx>
|
||||
|
||||
Bug fixes/reports and other suggestions from:
|
||||
|
||||
Remi Emonet <remi.emonet -at- inrialpes -dot- fr>
|
||||
Simon McVittie <simon -dot- mcvittie -at- collabora -dot- co -dot- uk>
|
||||
Dick Hollenbeck <dick -at- softplc -dot- com>
|
||||
Joshua Nichols <nichoj -at- gentoo -dot- org>
|
||||
Ralf Kistner <ralf.kistner -at- gmail -dot- com>
|
||||
Henrik Petander <henrik -dot- petander -at- iki -dot- fi>
|
||||
Luigi Paioro <luigi -at- lambrate -dot- it>
|
||||
Roberto Francisco Arroyo Moreno <robfram -at- ugr -dot- es>
|
||||
Steve Crane <Steve -dot Crane -at- rococosoft -dot- com>
|
||||
Philippe Marschall <philippe -dot- marschall -at- gmail -dot- com>
|
||||
Daniel Machado <cdanielmachado -at- gmail -dot- com>
|
||||
Anibal Sanchez <anibal -dot- sanchez -at- sunya -dot- com -dot- ar>
|
||||
Jan Kümmel <freedesktop -at- snorc -dot- org>
|
||||
Johannes Felten <johannesfelten -at- googlemail -dot- com>
|
||||
Tom Walsh <walshtc -at- gmail -dot- com>
|
||||
Ed Wei <Edward.Wei.03 -at- alum -dot- dartmouth -dot- org>
|
||||
Sveinung Kvilhaugsvik <sveinung84 -at- users -dot- sourceforge -dot- net>
|
||||
Hugues Moreau <hmoreau -at- gmail -dot- com>
|
||||
Viktar Vauchkevich <vctr -at- yandex -dot- ru>
|
||||
Serkan Kaba <serkan_kaba -at- yahoo -dot- com>
|
||||
Adam Bennett <cruxic -at- gmail -dot- com>
|
||||
Frank Benoit <benoit -at- tionex -dot- de>
|
||||
Gunnar Aastrand Grimnes <gunnar -dot- grimnes -at- dfki -dot- de>
|
||||
|
||||
The included Viewer application was originally written by:
|
||||
|
||||
Peter Cox <petercox -at- gawab -dot- com>
|
||||
|
||||
with patches from:
|
||||
|
||||
Zsombor Gegesy <gzsombor -at- gmail -dot- com>
|
680
federation/sssd/src/main/resources/DBUS-JAVA-LICENSE
Normal file
680
federation/sssd/src/main/resources/DBUS-JAVA-LICENSE
Normal file
|
@ -0,0 +1,680 @@
|
|||
The D-Bus Java implementation is licensed to you under your choice of the
|
||||
Academic Free License version 2.1, or the GNU Lesser/Library General Public License
|
||||
version 2. Both licenses are included here. Each source code file is marked
|
||||
with the proper copyright information.
|
||||
|
||||
The Academic Free License
|
||||
v. 2.1
|
||||
|
||||
This Academic Free License (the "License") applies to any original work of
|
||||
authorship (the "Original Work") whose owner (the "Licensor") has placed the
|
||||
following notice immediately following the copyright notice for the Original
|
||||
Work:
|
||||
|
||||
Licensed under the Academic Free License version 2.1
|
||||
|
||||
1) Grant of Copyright License. Licensor hereby grants You a world-wide,
|
||||
royalty-free, non-exclusive, perpetual, sublicenseable license to do the
|
||||
following:
|
||||
|
||||
a) to reproduce the Original Work in copies;
|
||||
|
||||
b) to prepare derivative works ("Derivative Works") based upon the Original
|
||||
Work;
|
||||
|
||||
c) to distribute copies of the Original Work and Derivative Works to the
|
||||
public;
|
||||
|
||||
d) to perform the Original Work publicly; and
|
||||
|
||||
e) to display the Original Work publicly.
|
||||
|
||||
2) Grant of Patent License. Licensor hereby grants You a world-wide,
|
||||
royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
|
||||
claims owned or controlled by the Licensor that are embodied in the Original
|
||||
Work as furnished by the Licensor, to make, use, sell and offer for sale the
|
||||
Original Work and Derivative Works.
|
||||
|
||||
3) Grant of Source Code License. The term "Source Code" means the preferred
|
||||
form of the Original Work for making modifications to it and all available
|
||||
documentation describing how to modify the Original Work. Licensor hereby
|
||||
agrees to provide a machine-readable copy of the Source Code of the Original
|
||||
Work along with each copy of the Original Work that Licensor distributes.
|
||||
Licensor reserves the right to satisfy this obligation by placing a
|
||||
machine-readable copy of the Source Code in an information repository
|
||||
reasonably calculated to permit inexpensive and convenient access by You for as
|
||||
long as Licensor continues to distribute the Original Work, and by publishing
|
||||
the address of that information repository in a notice immediately following
|
||||
the copyright notice that applies to the Original Work.
|
||||
|
||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
|
||||
of any contributors to the Original Work, nor any of their trademarks or
|
||||
service marks, may be used to endorse or promote products derived from this
|
||||
Original Work without express prior written permission of the Licensor. Nothing
|
||||
in this License shall be deemed to grant any rights to trademarks, copyrights,
|
||||
patents, trade secrets or any other intellectual property of Licensor except as
|
||||
expressly stated herein. No patent license is granted to make, use, sell or
|
||||
offer to sell embodiments of any patent claims other than the licensed claims
|
||||
defined in Section 2. No right is granted to the trademarks of Licensor even if
|
||||
such marks are included in the Original Work. Nothing in this License shall be
|
||||
interpreted to prohibit Licensor from licensing under different terms from this
|
||||
License any Original Work that Licensor otherwise would have a right to
|
||||
license.
|
||||
|
||||
5) This section intentionally omitted.
|
||||
|
||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative
|
||||
Works that You create, all copyright, patent or trademark notices from the
|
||||
Source Code of the Original Work, as well as any notices of licensing and any
|
||||
descriptive text identified therein as an "Attribution Notice." You must cause
|
||||
the Source Code for any Derivative Works that You create to carry a prominent
|
||||
Attribution Notice reasonably calculated to inform recipients that You have
|
||||
modified the Original Work.
|
||||
|
||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
|
||||
the copyright in and to the Original Work and the patent rights granted herein
|
||||
by Licensor are owned by the Licensor or are sublicensed to You under the terms
|
||||
of this License with the permission of the contributor(s) of those copyrights
|
||||
and patent rights. Except as expressly stated in the immediately proceeding
|
||||
sentence, the Original Work is provided under this License on an "AS IS" BASIS
|
||||
and WITHOUT WARRANTY, either express or implied, including, without limitation,
|
||||
the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
|
||||
This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
|
||||
license to Original Work is granted hereunder except under this disclaimer.
|
||||
|
||||
8) Limitation of Liability. Under no circumstances and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise, shall the
|
||||
Licensor be liable to any person for any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License
|
||||
or the use of the Original Work including, without limitation, damages for loss
|
||||
of goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses. This limitation of liability shall not
|
||||
apply to liability for death or personal injury resulting from Licensor's
|
||||
negligence to the extent applicable law prohibits such limitation. Some
|
||||
jurisdictions do not allow the exclusion or limitation of incidental or
|
||||
consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
9) Acceptance and Termination. If You distribute copies of the Original Work or
|
||||
a Derivative Work, You must make a reasonable effort under the circumstances to
|
||||
obtain the express assent of recipients to the terms of this License. Nothing
|
||||
else but this License (or another written agreement between Licensor and You)
|
||||
grants You permission to create Derivative Works based upon the Original Work
|
||||
or to exercise any of the rights granted in Section 1 herein, and any attempt
|
||||
to do so except under the terms of this License (or another written agreement
|
||||
between Licensor and You) is expressly prohibited by U.S. copyright law, the
|
||||
equivalent laws of other countries, and by international treaty. Therefore, by
|
||||
exercising any of the rights granted to You in Section 1 herein, You indicate
|
||||
Your acceptance of this License and all of its terms and conditions.
|
||||
|
||||
10) Termination for Patent Action. This License shall terminate automatically
|
||||
and You may no longer exercise any of the rights granted to You by this License
|
||||
as of the date You commence an action, including a cross-claim or counterclaim,
|
||||
against Licensor or any licensee alleging that the Original Work infringes a
|
||||
patent. This termination provision shall not apply for an action alleging
|
||||
patent infringement by combinations of the Original Work with other software or
|
||||
hardware.
|
||||
|
||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
|
||||
License may be brought only in the courts of a jurisdiction wherein the
|
||||
Licensor resides or in which Licensor conducts its primary business, and under
|
||||
the laws of that jurisdiction excluding its conflict-of-law provisions. The
|
||||
application of the United Nations Convention on Contracts for the International
|
||||
Sale of Goods is expressly excluded. Any use of the Original Work outside the
|
||||
scope of this License or after its termination shall be subject to the
|
||||
requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq.,
|
||||
the equivalent laws of other countries, and international treaty. This section
|
||||
shall survive the termination of this License.
|
||||
|
||||
12) Attorneys Fees. In any action to enforce the terms of this License or
|
||||
seeking damages relating thereto, the prevailing party shall be entitled to
|
||||
recover its costs and expenses, including, without limitation, reasonable
|
||||
attorneys' fees and costs incurred in connection with such action, including
|
||||
any appeal of such action. This section shall survive the termination of this
|
||||
License.
|
||||
|
||||
13) Miscellaneous. This License represents the complete agreement concerning
|
||||
the subject matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent necessary to
|
||||
make it enforceable.
|
||||
|
||||
14) Definition of "You" in This License. "You" throughout this License, whether
|
||||
in upper or lower case, means an individual or a legal entity exercising rights
|
||||
under, and complying with all of the terms of, this License. For legal
|
||||
entities, "You" includes any entity that controls, is controlled by, or is
|
||||
under common control with you. For purposes of this definition, "control" means
|
||||
(i) the power, direct or indirect, to cause the direction or management of such
|
||||
entity, whether by contract or otherwise, or (ii) ownership of fifty percent
|
||||
(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
|
||||
entity.
|
||||
|
||||
15) Right to Use. You may use the Original Work in all ways not otherwise
|
||||
restricted or conditioned by this License or by law, and Licensor promises not
|
||||
to interfere with or be responsible for such uses by You.
|
||||
|
||||
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
|
||||
Permission is hereby granted to copy and distribute this license without
|
||||
modification. This license may not be modified without the express written
|
||||
permission of its copyright owner.
|
||||
|
||||
|
||||
--
|
||||
END OF ACADEMIC FREE LICENSE. The following is intended to describe the
|
||||
essential differences between the Academic Free License (AFL) version 1.0 and
|
||||
other open source licenses:
|
||||
|
||||
The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache
|
||||
licenses in many respects but it is intended to solve a few problems with those
|
||||
licenses.
|
||||
|
||||
* The AFL is written so as to make it clear what software is being
|
||||
licensed (by the inclusion of a statement following the copyright notice in the
|
||||
software). This way, the license functions better than a template license. The
|
||||
BSD, MIT and UoI/NCSA licenses apply to unidentified software.
|
||||
|
||||
* The AFL contains a complete copyright grant to the software. The BSD
|
||||
and Apache licenses are vague and incomplete in that respect.
|
||||
|
||||
* The AFL contains a complete patent grant to the software. The BSD, MIT,
|
||||
UoI/NCSA and Apache licenses rely on an implied patent license and contain no
|
||||
explicit patent grant.
|
||||
|
||||
* The AFL makes it clear that no trademark rights are granted to the
|
||||
licensor's trademarks. The Apache license contains such a provision, but the
|
||||
BSD, MIT and UoI/NCSA licenses do not.
|
||||
|
||||
* The AFL includes the warranty by the licensor that it either owns the
|
||||
copyright or that it is distributing the software under a license. None of the
|
||||
other licenses contain that warranty. All other warranties are disclaimed, as
|
||||
is the case for the other licenses.
|
||||
|
||||
* The AFL is itself copyrighted (with the right granted to copy and distribute
|
||||
without modification). This ensures that the owner of the copyright to the
|
||||
license will control changes. The Apache license contains a copyright notice,
|
||||
but the BSD, MIT and UoI/NCSA licenses do not.
|
||||
|
||||
--
|
||||
START OF GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
--
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue