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;
|
return;
|
||||||
} else if (initOptions) {
|
} else if (initOptions) {
|
||||||
if (initOptions.token || initOptions.refreshToken) {
|
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;
|
kc.timeSkew = initOptions.timeSkew || 0;
|
||||||
|
|
||||||
if (loginIframe.enable) {
|
if (loginIframe.enable) {
|
||||||
|
@ -406,10 +406,10 @@
|
||||||
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
||||||
|
|
||||||
var tokenResponse = JSON.parse(req.responseText);
|
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;
|
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
||||||
|
|
||||||
|
setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
|
||||||
|
|
||||||
kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
|
kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
|
||||||
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
||||||
p.setSuccess(true);
|
p.setSuccess(true);
|
||||||
|
@ -444,7 +444,7 @@
|
||||||
|
|
||||||
kc.clearToken = function() {
|
kc.clearToken = function() {
|
||||||
if (kc.token) {
|
if (kc.token) {
|
||||||
setToken(null, null, null, true);
|
setToken(null, null, null);
|
||||||
kc.onAuthLogout && kc.onAuthLogout();
|
kc.onAuthLogout && kc.onAuthLogout();
|
||||||
if (kc.loginRequired) {
|
if (kc.loginRequired) {
|
||||||
kc.login();
|
kc.login();
|
||||||
|
@ -525,7 +525,7 @@
|
||||||
function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
|
function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
|
||||||
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
||||||
|
|
||||||
setToken(accessToken, refreshToken, idToken, true);
|
setToken(accessToken, refreshToken, idToken);
|
||||||
|
|
||||||
if ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
|
if ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
|
||||||
(kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
|
(kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
|
||||||
|
@ -609,7 +609,7 @@
|
||||||
return promise.promise;
|
return promise.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setToken(token, refreshToken, idToken, useTokenTime) {
|
function setToken(token, refreshToken, idToken) {
|
||||||
if (kc.tokenTimeoutHandle) {
|
if (kc.tokenTimeoutHandle) {
|
||||||
clearTimeout(kc.tokenTimeoutHandle);
|
clearTimeout(kc.tokenTimeoutHandle);
|
||||||
kc.tokenTimeoutHandle = null;
|
kc.tokenTimeoutHandle = null;
|
||||||
|
@ -629,9 +629,12 @@
|
||||||
kc.resourceAccess = kc.tokenParsed.resource_access;
|
kc.resourceAccess = kc.tokenParsed.resource_access;
|
||||||
|
|
||||||
if (kc.onTokenExpired) {
|
if (kc.onTokenExpired) {
|
||||||
var start = useTokenTime ? kc.tokenParsed.iat : (new Date().getTime() / 1000);
|
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
||||||
var expiresIn = kc.tokenParsed.exp - start;
|
if (expiresIn <= 0) {
|
||||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn * 1000);
|
kc.onTokenExpired();
|
||||||
|
} else {
|
||||||
|
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
7
dependencies/server-all/pom.xml
vendored
7
dependencies/server-all/pom.xml
vendored
|
@ -83,7 +83,6 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-kerberos-federation</artifactId>
|
<artifactId>keycloak-kerberos-federation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- saml -->
|
<!-- saml -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
|
@ -110,6 +109,12 @@
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Dependencies for RHEL IdM -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-sssd-federation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Built-in Authorization Policy Providers -->
|
<!-- Built-in Authorization Policy Providers -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<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-js-adapter" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-kerberos-federation" 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-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-server-spi" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-jpa" services="import"/>
|
<module name="org.keycloak.keycloak-model-jpa" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-mongo" 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>
|
<modules>
|
||||||
<module>ldap</module>
|
<module>ldap</module>
|
||||||
<module>kerberos</module>
|
<module>kerberos</module>
|
||||||
|
<module>sssd</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</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