summaryrefslogtreecommitdiff
path: root/src/com
diff options
context:
space:
mode:
authorAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
committerAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
commitaadeffb3f0716ffd231d1146d050847e3be355ee (patch)
tree9f2ed61a84a37fce5f154498023b28d6bfbf69bf /src/com
2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
* Initial commit.
Diffstat (limited to 'src/com')
-rw-r--r--src/com/Makefile.am1
-rw-r--r--src/com/sun/Makefile.am1
-rw-r--r--src/com/sun/apoc/Makefile.am1
-rw-r--r--src/com/sun/apoc/daemon/Makefile.am5
-rw-r--r--src/com/sun/apoc/daemon/admin/AdminManager.java286
-rw-r--r--src/com/sun/apoc/daemon/admin/AdminOpHandler.java43
-rw-r--r--src/com/sun/apoc/daemon/admin/PortMapper.java100
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/Cache.java927
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/CacheFactory.java151
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/CacheReadResult.java47
-rw-r--r--src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java93
-rw-r--r--src/com/sun/apoc/daemon/apocd/Client.java148
-rw-r--r--src/com/sun/apoc/daemon/apocd/ClientEventHandler.java79
-rw-r--r--src/com/sun/apoc/daemon/apocd/ClientManager.java311
-rw-r--r--src/com/sun/apoc/daemon/apocd/Daemon.java209
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventHandler.java42
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventQueue.java100
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventWorkerThread.java122
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java191
-rw-r--r--src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java56
-rw-r--r--src/com/sun/apoc/daemon/apocd/PolicyBackend.java366
-rw-r--r--src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java235
-rw-r--r--src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java221
-rw-r--r--src/com/sun/apoc/daemon/apocd/Session.java335
-rw-r--r--src/com/sun/apoc/daemon/apocd/SessionListener.java42
-rw-r--r--src/com/sun/apoc/daemon/apocd/UpdateAggregator.java92
-rw-r--r--src/com/sun/apoc/daemon/build.xml.in87
-rw-r--r--src/com/sun/apoc/daemon/config/ConfigEventListener.java40
-rw-r--r--src/com/sun/apoc/daemon/config/DaemonConfig.java418
-rw-r--r--src/com/sun/apoc/daemon/config/LocalConfig.java79
-rw-r--r--src/com/sun/apoc/daemon/config/RemoteConfig.java198
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/Database.java365
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java200
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java460
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/SetDbt.java96
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/StringDbt.java70
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/Timestamp.java108
-rwxr-xr-xsrc/com/sun/apoc/daemon/localdatabase/UpdateItem.java75
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/AddListenerMessage.java133
-rw-r--r--src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java111
-rw-r--r--src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java134
-rw-r--r--src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java41
-rw-r--r--src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java65
-rw-r--r--src/com/sun/apoc/daemon/messaging/ListMessage.java65
-rw-r--r--src/com/sun/apoc/daemon/messaging/Message.java80
-rw-r--r--src/com/sun/apoc/daemon/messaging/MessageFactory.java113
-rw-r--r--src/com/sun/apoc/daemon/messaging/Messenger.java91
-rw-r--r--src/com/sun/apoc/daemon/messaging/Notification.java119
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java72
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolHandler.java103
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java206
-rw-r--r--src/com/sun/apoc/daemon/messaging/ReadMessage.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/RequestReceiver.java92
-rw-r--r--src/com/sun/apoc/daemon/messaging/Response.java109
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCAuthenticator.java169
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCException.java98
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCLogger.java227
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCSymbols.java246
-rw-r--r--src/com/sun/apoc/daemon/misc/ConfigurableLogger.java72
-rw-r--r--src/com/sun/apoc/daemon/misc/DaemonTimerTask.java110
-rw-r--r--src/com/sun/apoc/daemon/misc/FileAccess.java42
-rw-r--r--src/com/sun/apoc/daemon/misc/Name.java128
-rw-r--r--src/com/sun/apoc/daemon/properties/apocd.properties66
-rw-r--r--src/com/sun/apoc/daemon/properties/daemon.properties82
-rw-r--r--src/com/sun/apoc/daemon/properties/defaults.properties83
-rw-r--r--src/com/sun/apoc/daemon/properties/os.properties.in4
-rw-r--r--src/com/sun/apoc/daemon/properties/policymgr.properties9
-rw-r--r--src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java58
-rw-r--r--src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java128
-rw-r--r--src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java76
-rw-r--r--src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java81
-rw-r--r--src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java56
-rw-r--r--src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java79
-rw-r--r--src/com/sun/apoc/daemon/transaction/ListTransaction.java82
-rw-r--r--src/com/sun/apoc/daemon/transaction/ReadTransaction.java86
-rw-r--r--src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java57
-rw-r--r--src/com/sun/apoc/daemon/transaction/Transaction.java148
-rw-r--r--src/com/sun/apoc/daemon/transaction/TransactionFactory.java181
-rw-r--r--src/com/sun/apoc/daemon/transport/ChannelManager.java414
-rw-r--r--src/com/sun/apoc/daemon/transport/ClientChannel.java150
-rw-r--r--src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java41
83 files changed, 11234 insertions, 0 deletions
diff --git a/src/com/Makefile.am b/src/com/Makefile.am
new file mode 100644
index 0000000..1d06788
--- /dev/null
+++ b/src/com/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = sun
diff --git a/src/com/sun/Makefile.am b/src/com/sun/Makefile.am
new file mode 100644
index 0000000..b5d5f2c
--- /dev/null
+++ b/src/com/sun/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = apoc
diff --git a/src/com/sun/apoc/Makefile.am b/src/com/sun/apoc/Makefile.am
new file mode 100644
index 0000000..75ad827
--- /dev/null
+++ b/src/com/sun/apoc/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = daemon
diff --git a/src/com/sun/apoc/daemon/Makefile.am b/src/com/sun/apoc/daemon/Makefile.am
new file mode 100644
index 0000000..f76f046
--- /dev/null
+++ b/src/com/sun/apoc/daemon/Makefile.am
@@ -0,0 +1,5 @@
+all:
+ $(ANT)
+
+clean-local:
+ $(ANT) -q clean
diff --git a/src/com/sun/apoc/daemon/admin/AdminManager.java b/src/com/sun/apoc/daemon/admin/AdminManager.java
new file mode 100644
index 0000000..3dfcf68
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/AdminManager.java
@@ -0,0 +1,286 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+
+public class AdminManager extends Thread
+{
+ private static final byte[] sSuccess = { 0 };
+ private static final byte[] sFailure = { 1 };
+ private static final byte sOpChangeDetect = ( byte )1;
+ private static final byte sOpReload = ( byte )6;
+ private static final byte sOpStatus = ( byte )9;
+ private static final byte sOpStop = ( byte )10;
+
+ private static final byte[] sAcceptByte = { 1 };
+ private static final ByteBuffer sAccept =
+ ( ByteBuffer )ByteBuffer.wrap( sAcceptByte );
+
+ private Selector mSelector;
+ private ServerSocketChannel mChannel;
+ private AdminOpHandler mAdminOpHandler;
+ private final Object mTerminateLock = new Object();
+ private boolean mTerminate = false;
+
+ public AdminManager( final AdminOpHandler inAdminOpHandler )
+ throws APOCException
+ {
+ setName( "AdminManager" );
+ mAdminOpHandler = inAdminOpHandler;
+ initChannel();
+ }
+
+ public void run()
+ {
+ APOCLogger.fine( "Admr001" );
+ while ( ! shouldTerminate() )
+ {
+ try
+ {
+ final ClientChannel theChannel = acceptClientChannel();
+ if ( theChannel != null )
+ {
+ if ( authenticate( theChannel ) )
+ {
+ try
+ {
+ handleRequest( theChannel );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "AdminManager",
+ "run",
+ theException );
+ }
+ }
+ theChannel.close();
+ }
+ }
+ catch ( IOException theException )
+ {
+ APOCLogger.throwing( "AdminManager", "run", theException );
+ break;
+ }
+ }
+ closeServerChannel();
+ APOCLogger.fine( "Admr002" );
+ }
+
+ public void terminate()
+ {
+ synchronized( mTerminateLock )
+ {
+ mTerminate = true;
+ }
+ }
+
+ private ClientChannel acceptClientChannel()
+ throws IOException
+ {
+ ClientChannel theChannel = null;
+ if ( mSelector.select() > 0 )
+ {
+ final Iterator theIterator = mSelector.selectedKeys().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey = ( SelectionKey )theIterator.next();
+ theIterator.remove();
+ if ( theKey.isAcceptable() )
+ {
+ SocketChannel theSocketChannel = null;
+ try
+ {
+ theSocketChannel =
+ (( ServerSocketChannel )theKey.channel() ).accept();
+ if ( theSocketChannel.
+ socket().
+ getInetAddress().
+ isLoopbackAddress() )
+ {
+ theChannel =
+ new ClientChannel( theSocketChannel, null);
+ theChannel.write( sAccept );
+ sAccept.flip();
+ break;
+ }
+ }
+ catch( IOException theException )
+ {
+ if ( theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.close();
+ }
+ catch( IOException ignore ){}
+ }
+ APOCLogger.throwing( "AdminManager",
+ "acceptClientChannel",
+ theException );
+ }
+ }
+ }
+ }
+ return theChannel;
+ }
+
+ private boolean authenticate( final ClientChannel inChannel )
+ {
+ boolean isAuthenticated;
+ APOCAuthenticator theAuthenticator = null;
+ try
+ {
+ theAuthenticator = new APOCAuthenticator( null );
+ byte[] theChallenge = theAuthenticator.getChallenge();
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( theChallenge.length + 1 )
+ .put( theChallenge )
+ .put( ( byte )0 )
+ .flip() );
+ ByteBuffer theAuthBuffer =
+ ByteBuffer.wrap(
+ new byte[ APOCAuthenticator.getAuthBufferSize() ] );
+ while ( inChannel.read( theAuthBuffer ) == 0 ){}
+ theAuthenticator.processResponse( theAuthBuffer.array() );
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( 1 ).put( sSuccess ).flip() );
+ isAuthenticated = true;
+ }
+ catch( Exception theException )
+ {
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( 1 ).put( sFailure ).flip() );
+ isAuthenticated = false;
+ }
+ finally
+ {
+ if ( theAuthenticator != null )
+ {
+ theAuthenticator.cleanup();
+ }
+ }
+ return isAuthenticated;
+ }
+
+ private void closeServerChannel()
+ {
+ try
+ {
+ mSelector.close();
+ mChannel.close();
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "AdminManager",
+ "closeServerChannel",
+ theException );
+ }
+ }
+
+ private void handleRequest( final ClientChannel inChannel )
+ throws Exception
+ {
+ int theRC;
+ ByteBuffer theBuffer = ByteBuffer.wrap( new byte[ 1 ] );
+ while ( inChannel.read( theBuffer ) != 1 ){}
+ switch( theBuffer.array()[ 0 ] )
+ {
+ case sOpStop:
+ theRC = mAdminOpHandler.onStop();
+ terminate();
+ break;
+
+ case sOpStatus:
+ theRC = mAdminOpHandler.onStatus();
+ break;
+
+ case sOpReload:
+ theRC = mAdminOpHandler.onReload();
+ break;
+
+ case sOpChangeDetect:
+ theRC = mAdminOpHandler.onChangeDetect();
+ break;
+
+ default:
+ theRC = -1;
+ break;
+ }
+ theBuffer = ByteBuffer.wrap( theRC == 0 ? sSuccess : sFailure );
+ inChannel.write( theBuffer );
+ }
+
+ private void initChannel()
+ throws APOCException
+ {
+ try
+ {
+ mSelector = Selector.open();
+ mChannel = ServerSocketChannel.open();
+ mChannel.configureBlocking( false );
+ mChannel.socket().bind( null );
+ mChannel.register( mSelector, SelectionKey.OP_ACCEPT );
+ /*
+ * 6417539 - Need to use IANA registered port
+ * Use a PortMapper instance to let admin. clients
+ * know which port the agent is using.
+ */
+ new PortMapper(
+ ( ( InetSocketAddress )mChannel.socket().getLocalSocketAddress() )
+ .getPort() ).start();
+ }
+ catch( IOException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ private boolean shouldTerminate()
+ {
+ synchronized( mTerminateLock )
+ {
+ return mTerminate;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/admin/AdminOpHandler.java b/src/com/sun/apoc/daemon/admin/AdminOpHandler.java
new file mode 100644
index 0000000..edc357c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/AdminOpHandler.java
@@ -0,0 +1,43 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+public interface AdminOpHandler
+{
+ int onStop();
+ int onStatus();
+ int onReload();
+ int onChangeDetect();
+}
diff --git a/src/com/sun/apoc/daemon/admin/PortMapper.java b/src/com/sun/apoc/daemon/admin/PortMapper.java
new file mode 100644
index 0000000..04c3b5f
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/PortMapper.java
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.net.*;
+
+/*
+ * Not really a port mapper but ....
+ *
+ * This class is used to inform admin. clients which port is currently being
+ * used for admin. access. It simply accepts a udp connection and reponds
+ * with the relevant port number. This is repeated indefinitely.
+ */
+public class PortMapper extends Thread
+{
+ private static int sPort =
+ DaemonConfig.getIntProperty( DaemonConfig.sDaemonPort );
+ private ByteBuffer mAdminPort;
+ private DatagramChannel mChannel;
+
+ public PortMapper( int inAdminPort )
+ throws APOCException
+ {
+ try
+ {
+ setName( "PortMapper" );
+ setDaemon( true );
+ mAdminPort =
+ ( ByteBuffer )ByteBuffer.allocate( 6 )
+ .put( String.valueOf( inAdminPort ).getBytes() )
+ .put( ( byte )0 );
+ mChannel = DatagramChannel.open();
+ mChannel.socket().bind( new InetSocketAddress( sPort ) );
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void run()
+ {
+ ByteBuffer theBuffer = ByteBuffer.allocate( 1 );
+ while ( true )
+ {
+ try
+ {
+ InetSocketAddress theClient =
+ ( InetSocketAddress )mChannel.receive(
+ ( ByteBuffer )theBuffer.position( 0 ) );
+ if ( theClient != null &&
+ theClient.getAddress().isLoopbackAddress() )
+ {
+ mChannel.send( ( ByteBuffer )mAdminPort.position( 0 ),
+ theClient );
+ }
+ }
+ catch( Exception theIgnore )
+ {}
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Cache.java b/src/com/sun/apoc/daemon/apocd/Cache.java
new file mode 100755
index 0000000..515ce09
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Cache.java
@@ -0,0 +1,927 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.policies.*;
+
+import java.util.*;
+import javax.security.auth.callback.*;
+
+
+public class Cache implements ConfigEventListener
+{
+ private String mUserName;
+ private String mEntityType;
+ private String mEntityId;
+ private CallbackHandler mHandler;
+ private DataSource mDataSources[] = null;
+ private final HashSet mSessions = new HashSet();
+ private int mRefCount = 0;
+ private boolean mIsLocalPolicyEnabled =
+ DaemonConfig.getBooleanProperty( DaemonConfig.sApplyLocalPolicy );
+ private static final String[] sStringModel = new String[ 0 ];
+
+ public Cache( final String inUserName,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler )
+ {
+ mUserName = inUserName;
+ mEntityType = inEntityType;
+ mEntityId = inEntityId;
+ mHandler = inHandler;
+ createDataSources();
+ inHandler.setReconnectMode();
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public synchronized int acquire( final Session inSession )
+ {
+ mSessions.add( inSession );
+ return ++ mRefCount;
+ }
+ public synchronized int release( final Session inSession )
+ {
+ mSessions.remove( inSession );
+ return -- mRefCount;
+ }
+ public synchronized Session [] getSessions()
+ {
+ return (Session []) mSessions.toArray(new Session [0]);
+ }
+ public synchronized ArrayList changeDetect()
+ {
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; ++ theIndex )
+ {
+ mDataSources[ theIndex ].open(mHandler);
+ }
+ ArrayList theResults = new ArrayList();
+ HashSet theOriginalList = null;
+ int theOnlineDataSourceCount = 0;
+
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; ++ theIndex )
+ {
+ if ( mDataSources[ theIndex ].isOnline())
+ {
+ ++ theOnlineDataSourceCount;
+ }
+ }
+ if ( theOnlineDataSourceCount > 1 )
+ {
+ theOriginalList = list();
+ }
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; theIndex ++ )
+ {
+ final ArrayList theResult =
+ changeDetect( mDataSources[ theIndex ] );
+ if ( theResult != null )
+ {
+ theResults.addAll( theResult );
+ }
+ }
+ if ( theOnlineDataSourceCount > 1 )
+ {
+ theResults = mergeUpdateResults( theResults, theOriginalList );
+ }
+ return theResults;
+ }
+
+ public synchronized void close()
+ {
+ for ( int theIndex = 0; theIndex < mDataSources.length ; theIndex ++ )
+ {
+ mDataSources[ theIndex ].close();
+ }
+ }
+
+ public String getEntityType() { return mEntityType; }
+
+ public String getEntityId() { return mEntityId; }
+
+ public boolean isOutOfDate()
+ {
+ long lastChangeDetect = Timestamp.getMillis(getLastChangeDetect()) ;
+
+ if (lastChangeDetect == 0) { return true ; }
+ return lastChangeDetect +
+ (long) (DaemonConfig.getFloatProperty(
+ DaemonConfig.sChangeDetectionInterval) * 60000) <
+ Timestamp.getMillis(Timestamp.getTimestamp()) ;
+ }
+
+ public synchronized String getLastChangeDetect()
+ {
+ String theResult = null;
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final LocalDatabase theDatabase =
+ mDataSources[ theIndex ].getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ final String theTimestamp=theDatabase.getLastChangeDetect();
+ if ( theTimestamp.compareTo( Timestamp.sEpoch ) == 0 )
+ {
+ break;
+ }
+ else if ( theResult == null )
+ {
+ theResult = theTimestamp;
+ }
+ else if ( Timestamp.isNewer( theResult, theTimestamp ) )
+ {
+ theResult = theTimestamp;
+ }
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "getLastChangeDetect",
+ theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "getLastChangeDetect",
+ theException );
+ }
+ }
+ }
+ }
+ return theResult != null ? theResult : Timestamp.sEpoch;
+ }
+
+ public String getUserId() { return mUserName; }
+
+ public synchronized boolean hasDatabase( final Database inDatabase )
+ {
+ boolean haveLocalDatabase = false;
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ if ( mDataSources[ theIndex ].getLocalDatabase() == inDatabase )
+ {
+ haveLocalDatabase = true;
+ break;
+ }
+ }
+ return haveLocalDatabase;
+ }
+
+ public synchronized HashSet list()
+ {
+ HashSet theComponents = new HashSet();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final HashSet theSet = list ( mDataSources[ theIndex ] );
+ if ( theSet != null )
+ {
+ theComponents.addAll( theSet );
+ }
+ }
+ return theComponents;
+ }
+
+ public synchronized void onConfigEvent()
+ {
+ boolean isLocalPolicyEnabled =
+ DaemonConfig.getBooleanProperty( DaemonConfig.sApplyLocalPolicy );
+ if ( isLocalPolicyEnabled != mIsLocalPolicyEnabled )
+ {
+ mIsLocalPolicyEnabled = isLocalPolicyEnabled;
+ if ( mIsLocalPolicyEnabled )
+ {
+ enableLocalPolicy();
+ }
+ else
+ {
+ disableLocalPolicy();
+ }
+ }
+ }
+
+ public synchronized ArrayList read( final String inComponentName )
+ {
+ final ArrayList theResults = new ArrayList();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final ArrayList theResult =
+ read( mDataSources[ theIndex ], inComponentName );
+ if ( theResult != null )
+ {
+ theResults.addAll( theResult );
+ }
+ }
+ return theResults;
+ }
+
+ public synchronized String toString()
+ {
+ final StringBuffer theBuffer = new StringBuffer();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ theBuffer.append( " dataSource" + ( theIndex + 1 ) )
+ .append( "\n " )
+ .append( mDataSources[ theIndex ].toString() )
+ .append( "\n" );
+ }
+ return theBuffer.toString();
+ }
+
+ private ArrayList changeDetect( final DataSource inDataSource )
+ {
+ ArrayList theResult = null;
+ if ( inDataSource.isOnline() )
+ {
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ try
+ {
+ theDatabase.beginTransaction();
+ switch( inDataSource.getState() )
+ {
+ case DataSource.sStateEnabled:
+ theResult = updateLocalDatabase( inDataSource );
+ break;
+
+ case DataSource.sStateDisabling:
+ theResult = new ArrayList();
+ addRemovalItems( theResult,
+ theDatabase.getLocalComponentList() );
+ break;
+ case DataSource.sStateEnabling:
+ theResult = new ArrayList();
+ addAdditionItems( theResult,
+ inDataSource,
+ theDatabase.getLocalComponentList() );
+ inDataSource.setState( DataSource.sStateEnabled );
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Cache", "changeDetect", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "changeDetect",
+ theException );
+ }
+ }
+ if ( inDataSource.mState == DataSource.sStateDisabling )
+ {
+ inDataSource.close();
+ }
+ }
+ return theResult;
+ }
+
+ private void createDataSources()
+ {
+ mDataSources = new DataSource [2];
+ mDataSources[ 0 ] = new DataSource( mUserName,
+ mEntityType,
+ mEntityId,
+ true );
+ mDataSources[ 1 ] = new DataSource( mUserName,
+ mEntityType,
+ mEntityId,
+ false );
+ if ( mIsLocalPolicyEnabled )
+ {
+ mDataSources[ 0 ].open( mHandler );
+ }
+ mDataSources[ 1 ].open( mHandler );
+ }
+
+ private void disableLocalPolicy()
+ {
+ mDataSources[ 0 ].setState( DataSource.sStateDisabling );
+ }
+
+ private void enableLocalPolicy()
+ {
+ mDataSources[ 0 ].setState( DataSource.sStateEnabling );
+ }
+
+ private HashSet list( final DataSource inDataSource )
+ {
+ HashSet theSet = null;
+ if ( inDataSource.getState() == DataSource.sStateEnabled )
+ {
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ theSet = theDatabase.getRemoteComponentList();
+ }
+ catch ( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "list", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "list", theException );
+ }
+ }
+ }
+ }
+ return theSet;
+ }
+
+ private ArrayList mergeUpdateResults( final ArrayList inResults,
+ final HashSet inOriginalList )
+ {
+ ArrayList theResult = inResults;
+ if ( inResults.size() > 0 &&
+ inOriginalList != null &&
+ inOriginalList.size() > 0 )
+ {
+ final HashSet theNewList = list();
+ final HashSet theUpdatedComponents = new HashSet();
+ final Iterator theIterator = inResults.iterator();
+ theResult = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ final UpdateItem theItem = ( UpdateItem )theIterator.next();
+ final String theName = theItem.getComponentName();
+ if ( theUpdatedComponents.add( theName ) )
+ {
+ if ( ( theItem.getUpdateType() == UpdateItem.ADD &&
+ inOriginalList.contains( theName ) ) ||
+ ( theItem.getUpdateType() == UpdateItem.REMOVE ) &&
+ theNewList.contains( theName ) )
+ {
+ theItem.setUpdateType( UpdateItem.MODIFY );
+ }
+ theResult.add( theItem );
+ }
+ }
+ }
+ return theResult;
+ }
+
+ private ArrayList read( final DataSource inDataSource,
+ final String inComponentName )
+ {
+ final ArrayList theResult = new ArrayList();
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ boolean haveComponent =
+ theDatabase.hasComponent( inComponentName );
+ if ( ! haveComponent && inDataSource.isOnline() )
+ {
+ final HashSet theSet = theDatabase.getRemoteComponentList();
+ if ( theSet != null && theSet.contains( inComponentName ) )
+ {
+ final Policy[] thePolicies =
+ inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies(
+ inComponentName,
+ false );
+ if ( thePolicies != null )
+ {
+ theDatabase.
+ update(
+ new UpdateItem(
+ UpdateItem.ADD,
+ inComponentName,
+ thePolicies ),
+ Timestamp.getTimestamp() );
+ haveComponent = true;
+ }
+ }
+ }
+ if ( haveComponent )
+ {
+ final Vector theLayerIds =
+ theDatabase.getLayerIds( inComponentName );
+ for ( int theIndex = 0;
+ theIndex < theLayerIds.size();
+ ++ theIndex )
+ {
+ final String theLayerId =
+ ( String )theLayerIds.elementAt( theIndex );
+ theResult.add(
+ new CacheReadResult(
+ theDatabase.
+ getLastModified( theLayerId,
+ inComponentName ),
+ theDatabase.
+ getLayer( inComponentName, theLayerId ) ) );
+ }
+ }
+ }
+ catch ( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "read", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "read", theException );
+ }
+ }
+ }
+ return theResult;
+ }
+
+ private void addDownloadItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inAddComponents,
+ final HashSet inModifyComponents )
+ throws APOCException
+ {
+ if ( inAddComponents != null && inModifyComponents != null )
+ {
+ final HashSet theSet = ( HashSet)inAddComponents.clone();
+ int theAddCount = theSet.size();
+ theSet.addAll( inModifyComponents );
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.getPolicyBackend().
+ getLayeredPolicies( theSet, false );
+ final Iterator theIterator = theSet.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ final String theComponent = ( String )theIterator.next();
+ outResult.add(
+ new UpdateItem( inAddComponents.contains( theComponent ) ?
+ UpdateItem.ADD : UpdateItem.MODIFY,
+ theComponent,
+ thePolicies[ theIndex ++ ] ) );
+ }
+
+ }
+ else
+ if ( inAddComponents != null )
+ {
+ addAdditionItems( outResult, inDataSource, inAddComponents );
+ }
+ else if ( inModifyComponents != null )
+ {
+ addModificationItems( outResult, inDataSource, inModifyComponents );
+ }
+
+ }
+
+ private void addAdditionItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inComponents, false );
+ final Iterator theIterator = inComponents.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.ADD,
+ ( String )theIterator.next(),
+ thePolicies[ theIndex ++ ] ) );
+ }
+ }
+ }
+
+ private void addModificationItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inComponents, false );
+ final Iterator theIterator = inComponents.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.MODIFY,
+ ( String )theIterator.next(),
+ thePolicies[ theIndex ++ ] ) );
+ }
+ }
+ }
+
+ private void addRemovalItems( final ArrayList outResult,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Iterator theIterator = inComponents.iterator();
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.REMOVE,
+ ( String )theIterator.next(),
+ null ) );
+ }
+ }
+ }
+
+ private int compareLayers( final DataSource inDataSource,
+ final String inComponentName,
+ final PolicyInfo[] inPolicies )
+ throws APOCException
+ {
+ int theRC = 0;
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ final Vector theLayerIds =
+ theDatabase.getLayerIds( inComponentName );
+ if ( theLayerIds.size() != inPolicies.length )
+ {
+ theRC = 1;
+ }
+ else
+ {
+ final String theComponentName = inPolicies[ 0 ].getId();
+ for ( int theIndex = 0 ; theIndex < inPolicies.length; ++ theIndex)
+ {
+ final String theLayerId =
+ ( String )theLayerIds.elementAt( theIndex );
+
+
+ if ( theLayerId.compareTo(
+ String.valueOf(
+ inPolicies[ theIndex ].getProfileId().hashCode() ) )
+ != 0
+ ||
+ Timestamp.getTimestamp(
+ inPolicies[ theIndex ].getLastModified() ).compareTo(
+ theDatabase.
+ getLastModified( theLayerId, theComponentName ))
+ != 0 )
+ {
+ theRC = 1;
+ break;
+ }
+ }
+ }
+ return theRC;
+ }
+
+ private void createUpdateItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inRemoteComponents )
+ throws APOCException
+ {
+ final HashSet theLocalComponents =
+ inDataSource.getLocalDatabase().getLocalComponentList();
+ final HashSet theAdditions =
+ diff( inRemoteComponents, theLocalComponents );
+ final HashSet theRemovals =
+ diff( theLocalComponents, inRemoteComponents );
+ final HashSet theModifications =
+ getModifications( inDataSource,
+ diff( theLocalComponents, theRemovals ) );
+ addDownloadItems( outResult,
+ inDataSource,
+ theAdditions,
+ theModifications );
+ addRemovalItems( outResult, theRemovals );
+ }
+
+ private HashSet diff( final HashSet inSet1, final HashSet inSet2 )
+ {
+ HashSet theResult = null;
+ if ( inSet2 == null )
+ {
+ theResult = inSet1;
+ }
+ else
+ if ( inSet1 != null )
+ {
+ theResult = ( HashSet )inSet1.clone();
+ theResult.removeAll( inSet2 );
+ if ( theResult.size() == 0 )
+ {
+ theResult = null;
+ }
+ }
+ return theResult;
+ }
+
+ private HashSet getModifications( final DataSource inDataSource,
+ final HashSet inSet )
+ throws APOCException
+ {
+ HashSet theModifications = null;
+ if ( inSet != null )
+ {
+ final PolicyInfo[][] thePolicies =
+ inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inSet, true );
+ final String[] theComponents =
+ ( String[] )inSet.toArray( sStringModel );
+ theModifications = new HashSet();
+ for ( int theIndex = 0 ; theIndex < thePolicies.length; ++ theIndex)
+ {
+ if ( isUpdated( inDataSource,
+ theComponents[ theIndex ],
+ thePolicies[ theIndex ] ) )
+ {
+ theModifications.add( theComponents[ theIndex ] );
+ }
+ }
+ if ( theModifications.size() == 0 )
+ {
+ theModifications = null;
+ }
+ }
+ return theModifications;
+ }
+
+ private boolean isUpdated( final DataSource inDataSource,
+ final String inComponent,
+ final PolicyInfo[] inPolicies )
+ throws APOCException
+ {
+ boolean isUpdated = false;
+ if ( inPolicies == null )
+ {
+ isUpdated = true;
+ }
+ else
+ {
+ isUpdated = compareLayers( inDataSource, inComponent, inPolicies )
+ == 0 ? false : true;
+ }
+ return isUpdated;
+ }
+
+ private ArrayList updateLocalDatabase( final DataSource inDataSource )
+ throws APOCException
+ {
+ final ArrayList theResult = new ArrayList();
+ try
+ {
+ final PolicyBackend theBackend = inDataSource.getPolicyBackend();
+ theBackend.refreshProfiles();
+ final HashSet theRemoteComponents = theBackend.getComponentList();
+ createUpdateItems( theResult, inDataSource, theRemoteComponents );
+ theResult.trimToSize();
+ final String theTimestamp= Timestamp.getTimestamp();
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ theDatabase.update( theResult, theTimestamp );
+ theDatabase.putLastChangeDetect( theTimestamp );
+ theDatabase.putRemoteComponentList(
+ theRemoteComponents != null ?
+ theRemoteComponents : new HashSet() );
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ return theResult;
+ }
+
+ private static class DataSource
+ {
+ protected LocalDatabase mLocalDatabase;
+ protected PolicyBackend mPolicyBackend;
+ protected Name mName;
+ protected int mState = sStateDisabled;
+ protected boolean mInitialised = false;
+
+ static final int sStateEnabled = 0;
+ static final int sStateDisabled = 1;
+ static final int sStateEnabling = 2;
+ static final int sStateDisabling = 3;
+
+ DataSource( final String inUserName,
+ final String inEntityType,
+ final String inEntityId,
+ final boolean inIsLocal )
+ {
+ mName = new Name( inUserName, inEntityType, inEntityId, inIsLocal );
+ }
+
+ void close()
+ {
+ closePolicyBackend();
+ closeLocalDatabase();
+ }
+
+ synchronized LocalDatabase getLocalDatabase() { return mLocalDatabase; }
+
+ synchronized PolicyBackend getPolicyBackend() { return mPolicyBackend; }
+
+ synchronized int getState() { return mState; }
+
+ synchronized boolean isOnline() {
+ return mPolicyBackend != null && mLocalDatabase != null; }
+
+ synchronized void open( final CallbackHandler inHandler )
+ {
+ boolean isLocal = mName.isLocal();
+ if ( ! isLocal ||
+ DaemonConfig.getBooleanProperty(
+ DaemonConfig.sApplyLocalPolicy ) )
+ {
+ if ( mLocalDatabase == null )
+ {
+ mLocalDatabase = openLocalDatabase();
+ }
+ try
+ {
+ if ( mLocalDatabase != null && mPolicyBackend == null &&
+ ( mInitialised ||
+ mLocalDatabase.getLastChangeDetect().compareTo(
+ Timestamp.sEpoch ) == 0 ) )
+ {
+ mPolicyBackend = openPolicyBackend( inHandler );
+ if ( ! mInitialised && mPolicyBackend != null )
+ {
+ initialiseDatabase();
+ }
+ }
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "DataSource", "open", theException );
+ }
+ mInitialised = true;
+ if ( ! isLocal || mState != sStateEnabling )
+ {
+ mState = sStateEnabled;
+ }
+ }
+ }
+
+ synchronized void setState( int inState ) { mState = inState; }
+
+ public String toString()
+ {
+ return new StringBuffer( " Name: " )
+ .append( mName.toString() )
+ .append( "\n Cache: " )
+ .append( mLocalDatabase )
+ .append( "\n Backend: " )
+ .append( mPolicyBackend )
+ .toString();
+ }
+
+ protected void initialiseDatabase()
+ {
+ try
+ {
+ final HashSet theSet = mPolicyBackend.getComponentList();
+ if ( theSet != null )
+ {
+ mLocalDatabase.beginTransaction();
+ mLocalDatabase.putRemoteComponentList( theSet );
+ mLocalDatabase.endTransaction();
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "DataSource",
+ "initialiseDatabase",
+ theException);
+ }
+ }
+
+ protected void closeLocalDatabase()
+ {
+ if ( mLocalDatabase != null )
+ {
+ try
+ {
+ LocalDatabaseFactory.getInstance().closeLocalDatabase(
+ mLocalDatabase );
+ }
+ catch( Exception theException ){}
+ finally { mLocalDatabase = null; }
+ }
+ }
+
+ protected void closePolicyBackend()
+ {
+ if ( mPolicyBackend != null )
+ {
+ PolicyBackendFactory.getInstance().closePolicyBackend(
+ mPolicyBackend );
+ mPolicyBackend = null;
+ }
+ }
+
+ protected LocalDatabase openLocalDatabase()
+ {
+ LocalDatabase theLocalDatabase = null;
+ try
+ {
+ theLocalDatabase =
+ LocalDatabaseFactory.getInstance().
+ openLocalDatabase( mName );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "DataSource",
+ "openLocalDatabase",
+ theException );
+ }
+ return theLocalDatabase;
+ }
+
+ protected PolicyBackend openPolicyBackend(
+ final CallbackHandler inHandler )
+ {
+ PolicyBackend theBackend = null;
+ try
+ {
+ theBackend =
+ PolicyBackendFactory
+ .getInstance()
+ .openPolicyBackend( mName, inHandler );
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "PolicyBackend",
+ "openPolicyBackend",
+ theException );
+ }
+ return theBackend;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/CacheFactory.java b/src/com/sun/apoc/daemon/apocd/CacheFactory.java
new file mode 100755
index 0000000..65d5f39
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/CacheFactory.java
@@ -0,0 +1,151 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class CacheFactory
+{
+ private final HashMap mCaches = new HashMap();
+ private static final CacheFactory sInstance = new CacheFactory();
+ private static final Cache[] sCacheModel = new Cache[ 0 ];
+
+ private synchronized void closeCache( final Cache inCache,
+ final Session inSession )
+ {
+ if ( inCache.release( inSession ) == 0 )
+ {
+ final Cache theCache =
+ ( Cache )mCaches.remove(
+ makeKey( inCache.getUserId(),
+ inCache.getEntityType(),
+ inCache.getEntityId() ) );
+ if ( theCache != null )
+ {
+ theCache.close();
+ }
+ }
+ }
+
+ public void closeCaches( final Cache[] inCaches, final Session inSession )
+ {
+ for ( int theIndex = 0 ; theIndex < inCaches.length ; ++ theIndex )
+ {
+ closeCache( inCaches[ theIndex ], inSession );
+ }
+ }
+
+ public synchronized Cache[] getCaches()
+ {
+ Cache[] theCaches = null;
+ if ( mCaches.size() > 0 )
+ {
+ theCaches = ( Cache[] )mCaches.values().toArray( sCacheModel );
+ }
+ return theCaches;
+ }
+
+ public static CacheFactory getInstance() { return sInstance; }
+
+ public synchronized Cache [] openCaches(
+ final String inUserId,
+ final Hashtable inEntities,
+ final Session inSession,
+ final SaslAuthCallbackHandler inHandler )
+ throws APOCException
+ {
+ String [] theSources = PolicyBackendFactory.getInstance().getSources();
+ ArrayList theCaches = new ArrayList();
+
+ for ( int theIndex = 0 ; theIndex < theSources.length ; ++ theIndex )
+ {
+ String theEntity =
+ (String) inEntities.get( theSources[ theIndex ] );
+ Cache theCache = getCache( inUserId, theSources[ theIndex ],
+ theEntity, inHandler );
+
+ theCache.acquire( inSession );
+ theCaches.add( theCache );
+ }
+ return (Cache []) theCaches.toArray( sCacheModel );
+ }
+
+ private CacheFactory(){}
+
+ private Cache getCache(final String inUserId,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler)
+ throws APOCException
+ {
+ Cache retCode = getExistingCache(inUserId, inEntityType, inEntityId) ;
+
+ if (retCode == null)
+ {
+ retCode = createNewCache(inUserId, inEntityType,
+ inEntityId, inHandler) ;
+ }
+ return retCode ;
+ }
+ private Cache createNewCache( final String inUserId,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler )
+ throws APOCException
+ {
+ Cache theCache = new Cache( inUserId, inEntityType,
+ inEntityId, inHandler );
+ mCaches.put( makeKey( inUserId, inEntityType, inEntityId ), theCache );
+ return theCache;
+ }
+
+ private Cache getExistingCache( final String inUserId,
+ final String inEntityType,
+ final String inEntityId )
+ {
+ return ( Cache )mCaches.get( makeKey( inUserId, inEntityType,
+ inEntityId ) );
+ }
+
+ private String makeKey( final String inUserId, final String inEntityType,
+ final String inEntityId )
+ {
+ return inUserId + "/" + inEntityType + "/" +
+ ( inEntityId != null ? inEntityId : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/CacheReadResult.java b/src/com/sun/apoc/daemon/apocd/CacheReadResult.java
new file mode 100755
index 0000000..e7e9a75
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/CacheReadResult.java
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+public class CacheReadResult
+{
+ public String mTimestamp;
+ public String mData;
+
+ public CacheReadResult( final String inTimestamp, final String inData )
+ {
+ mTimestamp = inTimestamp;
+ mData = inData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java b/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java
new file mode 100644
index 0000000..0ee5bb6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java
@@ -0,0 +1,93 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.transaction.*;
+
+class ChangeDetectEventHandler implements EventHandler
+{
+ private final ChangeDetectTransaction mTransaction;
+ private long sTimeout = 100;
+ private final Object mCompleteLock = new Object();
+ private boolean mComplete = false;
+
+ ChangeDetectEventHandler( final ClientManager inManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ mTransaction = TransactionFactory
+ .getInstance()
+ .createChangeDetectTransaction( inManager,
+ inCache,
+ inAggregator );
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ mTransaction.execute();
+ setComplete();
+ }
+
+ public synchronized void waitForCompletion()
+ {
+ while ( ! isComplete() )
+ {
+ try
+ {
+ wait( sTimeout );
+ }
+ catch( InterruptedException theException )
+ {}
+ }
+ }
+
+ private boolean isComplete()
+ {
+ synchronized( mCompleteLock )
+ {
+ return mComplete;
+ }
+ }
+
+ private void setComplete()
+ {
+ synchronized( mCompleteLock )
+ {
+ mComplete = true;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Client.java b/src/com/sun/apoc/daemon/apocd/Client.java
new file mode 100644
index 0000000..ff67959
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Client.java
@@ -0,0 +1,148 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+import java.util.*;
+
+public class Client
+{
+ private final ClientChannel mChannel;
+ private final HashMap mSessions = new HashMap( 1 ); // norm is 1 session
+ private final HashSet mSessionListeners = new HashSet( 1 );
+
+ public Client( final ClientChannel inChannel )
+ {
+ mChannel = inChannel;
+ }
+
+ public ClientChannel getClientChannel() { return mChannel; }
+
+ // Changing this from a simple accessor because when change detection
+ // and session closure occur around the same time, the toArray() call
+ // below ( originally located in ClientManager ) can get confused.
+ public Object[] getSessions()
+ {
+ synchronized( mSessions )
+ {
+ return mSessions.values().toArray();
+ }
+ }
+
+ public Session getSession( final String inSessionId )
+ {
+ synchronized( mSessions )
+ {
+ return inSessionId != null ?
+ ( Session )mSessions.get( inSessionId ):
+ null;
+ }
+ }
+
+ public void addSession( final Session inSession )
+ {
+ synchronized( mSessions )
+ {
+ mSessions.put( inSession.getSessionId(), inSession );
+ }
+ notifySessionCreated( inSession );
+ }
+
+ public void addSessionListener( final SessionListener inSessionListener )
+ {
+ synchronized( mSessionListeners )
+ {
+ mSessionListeners.add( inSessionListener );
+ }
+ }
+
+ public void closeSession( final Session inSession )
+ {
+ synchronized( mSessions )
+ {
+ mSessions.remove( inSession.getSessionId() );
+ }
+ inSession.close();
+ notifySessionDestroyed( inSession );
+ }
+
+ synchronized public void close()
+ {
+ final Iterator theIterator = mSessions.keySet().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final Session theSession =
+ ( Session )mSessions.get( theIterator.next() );
+ theSession.close();
+ notifySessionDestroyed( theSession );
+ }
+ mSessions.clear();
+ }
+
+ public void removeSessionListener( final SessionListener inSessionListener )
+ {
+ synchronized( mSessionListeners )
+ {
+ mSessionListeners.remove( inSessionListener );
+ }
+ }
+
+ private void notifySessionCreated( final Session inSession )
+ {
+ synchronized( mSessionListeners )
+ {
+ final Iterator theIterator = mSessionListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( SessionListener )theIterator.next() )
+ .onSessionCreate( inSession );
+ }
+ }
+ }
+
+ private void notifySessionDestroyed( final Session inSession )
+ {
+ synchronized( mSessionListeners )
+ {
+ final Iterator theIterator = mSessionListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( SessionListener )theIterator.next() )
+ .onSessionDestroy( inSession );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java b/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java
new file mode 100644
index 0000000..9df1cba
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+
+class ClientEventHandler implements EventHandler
+{
+ private final Client mClient;
+
+ ClientEventHandler( final Client inClient)
+ {
+ mClient = inClient;
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ try
+ {
+ inMessenger.setClientChannel( mClient.getClientChannel() );
+ final Transaction theTransaction =
+ TransactionFactory
+ .getInstance()
+ .createTransaction(
+ mClient,
+ inMessenger.receiveRequest() );
+ inMessenger.sendResponse( theTransaction.execute() );
+ }
+ catch( APOCException theException )
+ {
+ final Throwable theThrowable = theException.getCause();
+ if ( theThrowable == null || !(theThrowable instanceof IOException))
+ {
+ APOCLogger.throwing( "ClientEventHandler",
+ "handleEvent",
+ theException );
+ inMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespInvalidRequest, null, null ) );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ClientManager.java b/src/com/sun/apoc/daemon/apocd/ClientManager.java
new file mode 100644
index 0000000..061e184
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ClientManager.java
@@ -0,0 +1,311 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.util.*;
+
+public class ClientManager implements ClientChannelEventListener,
+ ConfigEventListener,
+ SessionListener
+{
+ private final HashMap mClients =
+ new HashMap( DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections ) );
+ private final EventQueue mPendingEvents =
+ new EventQueue();
+ private final EventWorkerThreadPool mThreadPool =
+ new EventWorkerThreadPool(
+ mPendingEvents,
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxClientThreads ) );
+ private final DaemonTimerTask mChangeDetector =
+ new DaemonTimerTask( new ChangeDetector( this ) );
+ private int mSessionCount = 0;
+
+ public ClientManager( final ChannelManager inChannelManager )
+ throws APOCException
+ {
+ inChannelManager.addClientChannelEventListener( this );
+ DaemonConfig.addConfigEventListener( this );
+ APOCLogger.fine( "Clmr001" );
+ }
+
+ public void changeDetect()
+ {
+ new ChangeDetector( this ).run();
+ }
+
+ public void onPending( final ClientChannel inClientChannel )
+ {
+ putEventHandler(
+ new ClientEventHandler( getClient( inClientChannel)) );
+ }
+
+ public void onClosed( final ClientChannel inClientChannel )
+ {
+ synchronized( mClients )
+ {
+ final Client theClient =
+ ( Client )mClients.remove( inClientChannel );
+ if ( theClient != null )
+ {
+ theClient.close();
+ APOCLogger.finer( "Clmr002" );
+ }
+ }
+ }
+
+ public void onConfigEvent()
+ {
+ startChangeDetectionTimer();
+
+ mThreadPool.resizePool(
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientThreads ) );
+ }
+
+ /* Warning: putting this here because we need access to the EventQueue.
+ * This Queue should be separated from this class in future.
+ */
+ public void onGarbageCollect()
+ {
+ try
+ {
+ Object[] theDatabases =
+ LocalDatabaseFactory.getInstance().getDatabases();
+ if ( theDatabases != null )
+ {
+ for ( int theIndex = 0;
+ theIndex < theDatabases.length;
+ ++ theIndex )
+ {
+ putEventHandler(
+ new GarbageCollectEventHandler(
+ ( Database )theDatabases[ theIndex ] ) );
+ }
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ClientManager",
+ "onGarbageCollect",
+ theException );
+ }
+ }
+
+ synchronized public void onSessionCreate( final Session inSession )
+ {
+ mSessionCount ++;
+ doInitialChangeDetect( inSession );
+ }
+
+ synchronized public void onSessionDestroy( final Session inSession )
+ {
+ mSessionCount --;
+ stopChangeDetectionTimer();
+ }
+
+ public void terminate()
+ {
+ mThreadPool.terminate();
+ APOCLogger.fine( "Clmr007" );
+ }
+
+ private void doInitialChangeDetect( final Session inSession )
+ {
+ try
+ {
+ Cache [] theCaches = inSession.getCaches() ;
+ ArrayList theOutOfDateCaches = new ArrayList() ;
+
+ for (int i = 0 ; i < theCaches.length ; ++ i)
+ {
+ if (theCaches [i].isOutOfDate())
+ {
+ theOutOfDateCaches.add(theCaches [i]) ;
+ }
+ }
+ final DaemonTimerTask theTask =
+ new DaemonTimerTask(
+ new ChangeDetector(
+ this,
+ (Cache []) theOutOfDateCaches.toArray(
+ new Cache [0])),
+ true) ;
+
+ theTask.setPeriod(
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sInitialChangeDetectionDelay) *
+ 1000) ;
+ startChangeDetectionTimer() ;
+ }
+ catch( Exception theException )
+ {}
+ }
+
+ private Client getClient( final ClientChannel inClientChannel )
+ {
+ synchronized( mClients )
+ {
+ Client theClient = ( Client )mClients.get( inClientChannel );
+ if ( theClient == null )
+ {
+ theClient = new Client( inClientChannel );
+ theClient.addSessionListener( this );
+ mClients.put( inClientChannel, theClient );
+ APOCLogger.finer( "Clmr005" );
+ }
+ return theClient;
+ }
+ }
+
+ private boolean putEventHandler( final EventHandler inEventHandler )
+ {
+ boolean theRC = true;
+ mPendingEvents.put( inEventHandler );
+ try
+ {
+ mThreadPool.ensureThread();
+ }
+ catch( APOCException theException )
+ {
+ theRC = false;
+ APOCLogger.throwing( "ChangeDetector", "run", theException );
+ }
+ return theRC;
+ }
+
+ private void startChangeDetectionTimer()
+ {
+ if ( mSessionCount > 0 )
+ {
+ final float theMinuteDelay =
+ DaemonConfig.getFloatProperty(
+ DaemonConfig.sChangeDetectionInterval );
+ if ( mChangeDetector.setPeriod( ( long )(60000 * theMinuteDelay) ) )
+ {
+ if ( mChangeDetector.getPeriod() > 0 )
+ {
+ APOCLogger.fine( "Clmr004",
+ String.valueOf( theMinuteDelay ) );
+ }
+ else
+ {
+ APOCLogger.fine( "Clmr006" );
+ }
+ }
+ }
+ }
+
+ private void stopChangeDetectionTimer()
+ {
+ if ( mSessionCount < 1 )
+ {
+ mChangeDetector.cancel();
+ }
+ }
+
+ static class ChangeDetector implements Runnable
+ {
+ private ClientManager mManager;
+ private Cache [] mCaches = null;
+ boolean mCheckCaches = false ;
+
+ public ChangeDetector( final ClientManager inManager,
+ final Cache [] inCaches )
+ {
+ mManager = inManager;
+ mCaches = inCaches ;
+ mCheckCaches = true ;
+ }
+
+ public ChangeDetector( final ClientManager inManager )
+ {
+ mManager = inManager;
+ }
+
+ public void run()
+ {
+ Cache [] theCaches = mCaches ;
+
+ if ( theCaches == null )
+ {
+ synchronized( mManager.mClients )
+ {
+ if ( ! mManager.mClients.isEmpty() )
+ {
+ theCaches = CacheFactory.getInstance().getCaches();
+ }
+ }
+ }
+ if ( theCaches != null )
+ {
+ final ArrayList theHandlers = new ArrayList();
+ final UpdateAggregator theAggregator = new UpdateAggregator() ;
+
+ for ( int theIndex = 0;
+ theIndex < theCaches.length;
+ ++ theIndex )
+ {
+ if (!mCheckCaches || theCaches [theIndex].isOutOfDate()) {
+ final ChangeDetectEventHandler theHandler =
+ new ChangeDetectEventHandler(
+ mManager, theCaches[ theIndex ],
+ theAggregator );
+ if ( mManager.putEventHandler( theHandler ) )
+ {
+ theHandlers.add( theHandler );
+ }
+ }
+ }
+ int theHandlerCount = theHandlers.size();
+ for ( int theIndex = 0;
+ theIndex < theHandlerCount;
+ ++ theIndex )
+ {
+ ( ( ChangeDetectEventHandler )theHandlers
+ .get( theIndex ) ).waitForCompletion();
+ }
+ theAggregator.sendNotifications() ;
+ mManager.startChangeDetectionTimer();
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Daemon.java b/src/com/sun/apoc/daemon/apocd/Daemon.java
new file mode 100644
index 0000000..8eddcaa
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Daemon.java
@@ -0,0 +1,209 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.admin.*;
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Daemon implements ConfigEventListener, AdminOpHandler
+{
+ private ChannelManager mChannelManager;
+ private ClientManager mClientManager;
+ private AdminManager mAdminManager;
+ private final DaemonTimerTask mGarbageCollector =
+ new DaemonTimerTask( new GarbageCollector() );
+
+ public static void main( final String[] inArgs )
+ {
+ try
+ {
+ new Daemon( inArgs ).run();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Daemon", "main", theException );
+ }
+ }
+
+ public Daemon( final String[] inArgs )
+ throws APOCException, IOException, InterruptedException
+ {
+ if ( inArgs.length != 2 )
+ {
+ usage();
+ System.exit( 1 );
+ }
+ init( inArgs );
+ }
+
+ public void onConfigEvent()
+ {
+ startGarbageCollectionTimer();
+ DaemonConfig.log();
+ }
+
+ public int onStop()
+ {
+ mChannelManager.terminate();
+ return 0;
+ }
+
+ public int onStatus()
+ {
+ return 0;
+ }
+
+ public int onReload()
+ {
+ int theRC;
+ try
+ {
+ DaemonConfig.reload();
+ DaemonConfig.log();
+ theRC = 0;
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Daemon", "onReload", theException );
+ theRC = 1;
+ }
+ return theRC;
+ }
+
+ public int onChangeDetect()
+ {
+ mClientManager.changeDetect();
+ return 0;
+ }
+
+ public void run()
+ throws APOCException, InterruptedException
+ {
+ APOCLogger.info( "Dmon001" );
+
+ startGarbageCollectionTimer();
+ mChannelManager = new ChannelManager();
+ mClientManager = new ClientManager( mChannelManager );
+ verifyConfig();
+ mChannelManager.start();
+ DaemonConfig.addConfigEventListener( this );
+ mAdminManager = new AdminManager( this );
+ mAdminManager.start();
+ mChannelManager.join();
+
+ mClientManager.terminate();
+ mChannelManager.closeChannels();
+ APOCLogger.info( "Dmon002" );
+ }
+
+ private void usage()
+ {
+ System.err.println( "Usage: apocd <daemon installation directory>" );
+ }
+
+ private void init( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ System.loadLibrary( "FileAccess" );
+ initConfig( inArgs );
+ initAuthDir();
+ }
+
+ private void initAuthDir()
+ throws APOCException
+ {
+ if ( ! APOCAuthenticator.sAuthDir.exists() )
+ {
+ if ( ! APOCAuthenticator.sAuthDir.mkdirs() )
+ {
+ throw new APOCException();
+ }
+ }
+ else
+ {
+ if ( ! APOCAuthenticator.sAuthDir.isDirectory() )
+ {
+ throw new APOCException();
+ }
+ }
+ FileAccess.chmod( APOCAuthenticator.sAuthDir.getAbsolutePath(), 0755 );
+ FileAccess.chmod( APOCAuthenticator.sAuthDir.getParent(), 0755 );
+ }
+
+ private void initConfig( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ DaemonConfig.init( inArgs );
+ DaemonConfig.log();
+ }
+
+ private void startGarbageCollectionTimer()
+ {
+ final long theMinuteDelay =
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sGarbageCollectionInterval );
+ if ( mGarbageCollector.setPeriod( 60000 * theMinuteDelay ) )
+ {
+ if ( mGarbageCollector.getPeriod() > 0 )
+ {
+ APOCLogger.fine( "Dmon003", String.valueOf( theMinuteDelay ) );
+ }
+ else
+ {
+ APOCLogger.fine( "Dmon004" );
+ }
+ }
+ }
+
+ private void verifyConfig()
+ throws APOCException
+ {
+ LocalDatabaseFactory.getInstance();
+ }
+
+ class GarbageCollector implements Runnable
+ {
+ public void run()
+ {
+ mClientManager.onGarbageCollect();
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventHandler.java b/src/com/sun/apoc/daemon/apocd/EventHandler.java
new file mode 100644
index 0000000..a1550a4
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventHandler.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+
+interface EventHandler
+{
+ public void handleEvent( final Messenger inMessenger );
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventQueue.java b/src/com/sun/apoc/daemon/apocd/EventQueue.java
new file mode 100644
index 0000000..b913754
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventQueue.java
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import java.util.*;
+
+class EventQueue
+{
+ private final List mList = new ArrayList();
+ static private final long sTimeout = 100;
+
+ public void put( final EventHandler inEventHandler )
+ {
+ add( inEventHandler );
+ synchronized( mList )
+ {
+ mList.notify();
+ }
+ }
+
+ public EventHandler get()
+ {
+ EventHandler theEventHandler = remove();
+ if ( theEventHandler == null )
+ {
+ try
+ {
+ synchronized( mList )
+ {
+ mList.wait( sTimeout );
+ }
+ }
+ catch ( InterruptedException theException )
+ {}
+ theEventHandler = remove();
+ }
+ return theEventHandler;
+ }
+
+ public void releaseWaitingThreads()
+ {
+ synchronized( mList )
+ {
+ mList.notifyAll();
+ }
+ }
+
+ private void add( final EventHandler inEventHandler )
+ {
+ synchronized( mList )
+ {
+ mList.add( inEventHandler );
+ }
+ }
+
+ private EventHandler remove()
+ {
+ EventHandler theEventHandler = null;
+ synchronized( mList )
+ {
+ if ( ! mList.isEmpty() )
+ {
+ theEventHandler = ( EventHandler )mList.remove( 0 );
+ }
+ }
+ return theEventHandler;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java b/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java
new file mode 100644
index 0000000..bfef9f7
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java
@@ -0,0 +1,122 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+import java.util.*;
+
+class EventWorkerThread extends Thread
+{
+ private final EventQueue mQueue;
+ private final Messenger mMessenger = new Messenger();
+ private final Object mStateLock = new Object();
+ private long mTimestamp = System.currentTimeMillis();
+ private int mState = sStateIdle;
+
+ private static int sStateIdle = 0;
+ private static int sStateBusy = 1;
+ private static int sStateTerminating = 2;
+ private static long sIdleTimeout =
+ ( long )DaemonConfig.
+ getIntProperty( DaemonConfig.sThreadTimeToLive ) * 60000;
+
+ public EventWorkerThread( final EventQueue inQueue )
+ throws APOCException
+ {
+ setName( "EventWorker" );
+ setDaemon( true );
+ mQueue = inQueue;
+ }
+
+ public boolean isAvailable()
+ {
+ return privgetState() == sStateIdle;
+ }
+
+ public void run()
+ {
+ while ( ! ( privgetState() == sStateTerminating ) )
+ {
+ final EventHandler theEventHandler = mQueue.get();
+ if ( theEventHandler != null )
+ {
+ setState( sStateBusy );
+ theEventHandler.handleEvent( mMessenger );
+ setState( sStateIdle );
+ }
+ }
+ }
+
+ public boolean terminate( boolean inIfIdle )
+ {
+ boolean isTerminated = true;
+ if ( ! inIfIdle )
+ {
+ setState( sStateTerminating );
+ }
+ else
+ {
+ long theIdleTime =
+ privgetState() == sStateIdle ?
+ System.currentTimeMillis() - mTimestamp : 0;
+ if ( theIdleTime > sIdleTimeout )
+ {
+ setState( sStateTerminating );
+ }
+ else
+ {
+ isTerminated = false;
+ }
+ }
+ return isTerminated;
+ }
+
+ private synchronized int privgetState() { return mState; }
+
+ private synchronized void setState( int inState )
+ {
+ if ( mState != sStateTerminating )
+ {
+ mTimestamp = inState == sStateTerminating ?
+ 0 : System.currentTimeMillis();
+ mState = inState;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java b/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java
new file mode 100644
index 0000000..191015b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java
@@ -0,0 +1,191 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+import java.util.*;
+
+class EventWorkerThreadPool
+{
+ private final EventQueue mQueue;
+ private final ArrayList mPool = new ArrayList();
+ private int mMaxPoolSize;
+ private int mPoolSize = 0;
+ private final DaemonTimerTask mIdleDetector =
+ new DaemonTimerTask( new IdleDetector() );
+
+ private static long sIdleDetectorPeriod =
+ ( long )DaemonConfig.
+ getIntProperty( DaemonConfig.sIdleThreadDetectionInterval ) * 60000;
+
+ public EventWorkerThreadPool( final EventQueue inQueue,
+ final int inPoolSize )
+ throws APOCException
+ {
+ mQueue = inQueue;
+ mMaxPoolSize = inPoolSize;
+ mIdleDetector.setPeriod( sIdleDetectorPeriod );
+ }
+
+ synchronized public void ensureThread()
+ throws APOCException
+ {
+ if ( mPoolSize < mMaxPoolSize && ! haveIdleThread() )
+ {
+ final EventWorkerThread theThread = new EventWorkerThread( mQueue );
+ mPool.add( theThread );
+ mPoolSize ++;
+ theThread.start();
+ }
+ }
+
+ synchronized public void resizePool( int inPoolSize )
+ {
+ inPoolSize = inPoolSize > 0 ? inPoolSize : 1;
+ if ( inPoolSize != mMaxPoolSize )
+ {
+ if ( inPoolSize > mMaxPoolSize )
+ {
+ mMaxPoolSize = inPoolSize;
+ }
+ else if ( inPoolSize < mMaxPoolSize )
+ {
+ shrinkPool( inPoolSize );
+ }
+ }
+ }
+
+ public synchronized void terminate()
+ {
+ terminateThreads();
+ waitForLiveThreads();
+ }
+
+ private boolean haveIdleThread()
+ {
+ boolean haveIdleThread = false;
+ for ( int theIndex = 0; theIndex < mPoolSize; theIndex ++ )
+ {
+ if ( ( ( EventWorkerThread )mPool.get( theIndex ) ).isAvailable() )
+ {
+ haveIdleThread = true;
+ break;
+ }
+ }
+ return haveIdleThread;
+ }
+
+ private boolean haveLiveThread()
+ {
+ boolean haveLiveThread = false;
+ for ( int theIndex = 0; theIndex < mPoolSize; theIndex ++ )
+ {
+ if ( ( ( EventWorkerThread )mPool.get( theIndex ) ).isAlive() )
+ {
+ haveLiveThread = true;
+ break;
+ }
+ }
+ return haveLiveThread;
+ }
+
+ private void shrinkPool( int inPoolSize )
+ {
+ for ( int theIndex = mPoolSize; theIndex > inPoolSize; theIndex -- )
+ {
+ ( ( EventWorkerThread )( mPool.remove( 0 ) ) ).terminate( false );
+ }
+ mPool.trimToSize();
+ mMaxPoolSize = inPoolSize;
+ }
+
+ private void terminateThreads()
+ {
+ terminateThreads( false );
+ }
+
+ private synchronized void terminateThreads( boolean inIdleOnly )
+ {
+ int theTerminatedCount = 0;
+ for ( int theIndex = mPoolSize - 1; theIndex >= 0; theIndex -- )
+ {
+ EventWorkerThread theThread =
+ ( EventWorkerThread )mPool.get( theIndex );
+ if ( theThread.terminate( inIdleOnly ) )
+ {
+ mPool.remove( theIndex );
+ theTerminatedCount ++;
+ }
+ }
+ if ( theTerminatedCount > 0 )
+ {
+ mQueue.releaseWaitingThreads();
+ mPoolSize -= theTerminatedCount;
+ }
+ }
+
+ private void waitForLiveThreads()
+ {
+ for ( int theIndex = 0; theIndex < 5; theIndex ++ )
+ {
+ if ( haveLiveThread() )
+ {
+ try
+ {
+ wait( 1000 );
+ }
+ catch( Exception theException ){}
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ class IdleDetector implements Runnable
+ {
+ public void run()
+ {
+ terminateThreads( true );
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java b/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java
new file mode 100644
index 0000000..8c09ba5
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.transaction.*;
+
+class GarbageCollectEventHandler implements EventHandler
+{
+ private final GarbageCollectTransaction mTransaction;
+
+ GarbageCollectEventHandler( final Database inDatabase )
+ {
+ mTransaction = TransactionFactory
+ .getInstance()
+ .createGarbageCollectTransaction( inDatabase );
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ mTransaction.execute();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/PolicyBackend.java b/src/com/sun/apoc/daemon/apocd/PolicyBackend.java
new file mode 100644
index 0000000..66e8401
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/PolicyBackend.java
@@ -0,0 +1,366 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.policies.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class PolicyBackend
+{
+ protected static final PolicyInfo[] sPolicyInfoModel= new PolicyInfo[ 0 ];
+ protected static final Policy[] sPolicyModel = new Policy[ 0 ];
+ protected static final Profile[] sProfileModel = new Profile[ 0 ];
+
+ protected Name mName;
+ protected PolicyManager mPolicyMgr;
+ protected Entity mEntity;
+ protected Profile[] mProfiles;
+ private int mRefCount = 0;
+ private Object mLock = new Object();
+ private boolean mProfilesInitialised = false;
+
+ public synchronized int acquire() { return ++ mRefCount; }
+ public synchronized int release() { return -- mRefCount; }
+
+ public PolicyBackend( final Name inName,
+ final Properties inProperties )
+ throws APOCException
+ {
+ mName = inName;
+ try
+ {
+ mPolicyMgr =
+ PolicyBackendFactory
+ .getInstance()
+ .openPolicyMgr( inProperties, mName );
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void close()
+ {
+ PolicyBackendFactory.getInstance().closePolicyMgr( mPolicyMgr );
+ }
+
+ public String toString() { return mName.toString() ; }
+
+ public synchronized HashSet getComponentList()
+ throws APOCException
+ {
+ try
+ {
+ initProfiles();
+ HashSet theComponentList = null;
+ if ( mProfiles != null && mProfiles.length > 0 )
+ {
+ theComponentList = new HashSet();
+ for ( int theIndex = 0;
+ theIndex < mProfiles.length;
+ theIndex ++ )
+ {
+ Iterator theIterator = mProfiles[ theIndex ].getPolicies();
+ if ( theIterator != null )
+ {
+ while ( theIterator.hasNext() )
+ {
+ Policy policy = (Policy) theIterator.next() ;
+
+ theComponentList.add(policy.getId()) ;
+ }
+ }
+ }
+ }
+ return theComponentList;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public synchronized PolicyInfo[][] getLayeredPolicies(
+ final Set inComponentList,
+ boolean inTimeStampOnly )
+ throws APOCException
+ {
+ try
+ {
+ initProfiles();
+ PolicyInfo[][] thePolicies = null;
+
+ if ( inComponentList != null &&
+ mProfiles != null &&
+ mProfiles.length > 0 )
+ {
+ int theIndex;
+ int theComponentCount = inComponentList.size();
+ if ( theComponentCount > 0 )
+ {
+ final Hashtable theTable =
+ new Hashtable( theComponentCount );
+ final ArrayList theComponentList =
+ new ArrayList( inComponentList );
+ for ( theIndex = 0;
+ theIndex < theComponentCount;
+ ++ theIndex )
+ {
+ theTable.put( theComponentList.get( theIndex ),
+ new ArrayList() );
+ }
+ for ( theIndex = 0;
+ theIndex < mProfiles.length;
+ ++ theIndex )
+ {
+ final Iterator theIterator =
+ inTimeStampOnly ?
+ mProfiles[ theIndex ].getPolicyInfos(
+ inComponentList.iterator() ) :
+ mProfiles[ theIndex ].getPolicies(
+ inComponentList.iterator() );
+ while ( theIterator.hasNext() )
+ {
+ final PolicyInfo thePolicy =
+ ( PolicyInfo )theIterator.next();
+ ( ( ArrayList )theTable.get( thePolicy.getId() ) )
+ .add( thePolicy );
+ }
+ }
+ thePolicies = inTimeStampOnly ?
+ new PolicyInfo[ theComponentCount ][] :
+ new Policy[ theComponentCount ][];
+ for ( theIndex = 0;
+ theIndex < theComponentCount;
+ ++ theIndex )
+ {
+ ArrayList theList =
+ ( ArrayList )theTable.get(
+ theComponentList.get( theIndex ) );
+ theList.trimToSize();
+ if ( theList.size() > 0 )
+ {
+ thePolicies[ theIndex ] =
+ inTimeStampOnly ?
+ ( PolicyInfo[] )theList.
+ toArray( sPolicyInfoModel ) :
+ ( Policy[] )theList.toArray( sPolicyModel );
+ }
+ else
+ {
+ thePolicies[ theIndex ] = null;
+ }
+ }
+ }
+ }
+ return thePolicies;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public synchronized Policy[] getLayeredPolicies(
+ final String inComponentName,
+ boolean inTimeStampOnly )
+ throws APOCException
+ {
+ try
+ {
+ Policy[] thePolicies = null;
+
+ if ( inComponentName != null )
+ {
+ if ( mProfiles != null && mProfiles.length > 0 )
+ {
+ ArrayList theList = new ArrayList();
+ for ( int theIndex = 0;
+ theIndex < mProfiles.length;
+ ++ theIndex )
+ {
+ Policy thePolicy = mProfiles[ theIndex ].
+ getPolicy( inComponentName );
+ if ( thePolicy != null )
+ {
+ theList.add( thePolicy );
+ }
+ }
+ theList.trimToSize();
+ if ( theList.size() > 0 )
+ {
+ thePolicies =
+ ( Policy[] )theList.toArray( sPolicyModel );
+ }
+ }
+ }
+ return thePolicies;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public Name getName() { return mName; }
+
+ public synchronized void refreshProfiles()
+ throws SPIException
+ {
+ if ( mName.isLocal() )
+ {
+ refreshLocalProfiles();
+ }
+ else
+ {
+ refreshGlobalProfiles();
+ }
+ }
+
+ private Entity findEntity()
+ {
+ Entity theEntity = null;
+
+ try
+ {
+ final Node theRoot =
+ ( Node ) mPolicyMgr.getRootEntity( mName.getEntityType() );
+ final Iterator theIterator =
+ theRoot.findEntities( mName.getEntityName(), true );
+ if ( theIterator != null && theIterator.hasNext() )
+ {
+ theEntity = ( Entity ) theIterator.next();
+ }
+ }
+ catch ( Exception theException ){}
+ return theEntity;
+ }
+
+ private void initProfiles()
+ throws SPIException
+ {
+ // There are two special cases to handle here
+ // 1. Creation of a first ever session for a user.
+ // In this case, we need to write the remote component list to bdb
+ // and we need profiles to figure out the list
+ // 2. Reading a component for the first time
+ // If a component isn't yet in bdb, we'll need the profiles to
+ // get the appropriate layers
+ synchronized( mLock )
+ {
+ if ( ! mProfilesInitialised )
+ {
+ refreshProfiles();
+ mProfilesInitialised = true;
+ }
+ }
+ }
+
+ private void refreshGlobalProfiles()
+ throws SPIException
+ {
+ mProfiles = null;
+ if ( mEntity == null )
+ {
+ mEntity = findEntity();
+ }
+ if ( mEntity != null )
+ {
+ final Iterator theIterator = mEntity.getLayeredProfiles();
+ if ( theIterator != null )
+ {
+ final ArrayList theProfiles = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ theProfiles.add( theIterator.next() );
+ }
+ if ( mEntity instanceof User )
+ {
+ final Profile theProfile =
+ ( ( User ) mEntity ).getUserProfile();
+ if ( theProfile != null )
+ {
+ theProfiles.add( theProfile );
+ }
+ }
+ if ( theProfiles.size() > 0 )
+ {
+ mProfiles =
+ ( Profile[] )theProfiles.toArray( sProfileModel );
+ }
+ }
+ }
+ }
+
+ private void refreshLocalProfiles()
+ throws SPIException
+ {
+ mProfiles = null;
+ final ProfileProvider theProvider =
+ mPolicyMgr.getProfileProvider( mName.getEntityType() );
+ final Iterator theIterator = theProvider.getAllProfiles();
+
+ if ( theIterator != null )
+ {
+ final ArrayList theProfiles = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ final Profile theProfile = ( Profile )theIterator.next();
+ final Applicability theApp = theProfile.getApplicability();
+ if ( theApp.equals( Applicability.ALL ) ||
+ theApp.equals( mName.getEntityType() ) )
+ {
+ theProfiles.add( theProfile );
+ }
+ }
+ if ( theProfiles.size() > 0 )
+ {
+ mProfiles =
+ ( Profile[] )theProfiles.toArray( sProfileModel );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java b/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java
new file mode 100644
index 0000000..35dddf9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java
@@ -0,0 +1,235 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.io.*;
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class PolicyBackendFactory
+{
+ public static int sTypeHost = 0;
+ public static int sTypeUser = 1;
+ public static final String sLocalHostName = "localHost";
+ public static final String sLocalUserName = "localUsers";
+ public static final Properties sLocalProperties= new Properties();
+
+ private HashMap mPolicyBackends = new HashMap();
+ private HashMap mPolicyMgrs = new HashMap();
+ private static PolicyBackendFactory sInstance;
+ private static final String sLocalPolicyDir =
+ new StringBuffer( "file://" )
+ .append( DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( "/" )
+ .append( "Policies/" )
+ .toString();
+
+ static
+ {
+ sLocalProperties.setProperty(
+ EnvironmentConstants.URL_KEY, sLocalPolicyDir );
+ String sourcesList =
+ (String) ((Properties) DaemonConfig.getLocalConfig()).get(
+ EnvironmentConstants.SOURCES_KEY) ;
+
+ if (sourcesList != null) {
+ sLocalProperties.setProperty(EnvironmentConstants.SOURCES_KEY,
+ sourcesList);
+ }
+ try
+ {
+ new File (
+ new java.net.URI( sLocalPolicyDir + "/assignments" ) ).mkdirs();
+ new File (
+ new java.net.URI( sLocalPolicyDir + "/profiles" ) ).mkdirs();
+ new File (
+ new java.net.URI(
+ sLocalPolicyDir + "/entities.txt" ) ).createNewFile();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "PolicyBackendFactory", "init", theException );
+ }
+ }
+
+ public void closePolicyBackend( final PolicyBackend inPolicyBackend )
+ {
+ synchronized( mPolicyBackends )
+ {
+ if ( inPolicyBackend.release() == 0 )
+ {
+ inPolicyBackend.close();
+ mPolicyBackends.remove(
+ createPolicyBackendKey( inPolicyBackend.getName() ) );
+ }
+ }
+ }
+
+ public void closePolicyMgr( final PolicyManager inPolicyMgr )
+ {
+ synchronized( mPolicyMgrs )
+ {
+ final RefCountedPolicyMgr thePolicyMgr =
+ ( RefCountedPolicyMgr )inPolicyMgr;
+ if ( thePolicyMgr.release() == 0 )
+ {
+ try
+ {
+ thePolicyMgr.close();
+ }
+ catch( SPIException theException ){}
+ mPolicyMgrs.remove(
+ createPolicyMgrKey( thePolicyMgr.mName ) );
+ }
+ }
+ }
+
+ public static PolicyBackendFactory getInstance()
+ {
+ if ( sInstance == null )
+ {
+ sInstance = new PolicyBackendFactory();
+ }
+ return sInstance;
+ }
+
+ public PolicyBackend openPolicyBackend(
+ final Name inName,
+ final CallbackHandler inHandler )
+ throws APOCException
+ {
+ final String theKey = createPolicyBackendKey( inName );
+ PolicyBackend theBackend = null;
+ synchronized( mPolicyBackends )
+ {
+ theBackend = ( PolicyBackend )mPolicyBackends.get( theKey );
+ if ( theBackend == null )
+ {
+ final Properties theProperties = inName.isLocal() ?
+ sLocalProperties :
+ ( Properties )(
+ ( Properties )DaemonConfig.getLocalConfig() ).clone();
+ if ( inHandler != null )
+ {
+ theProperties.put( EnvironmentConstants.LDAP_AUTH_CBH,
+ inHandler );
+ }
+ theBackend = new PolicyBackend( inName, theProperties );
+ mPolicyBackends.put( theKey, theBackend );
+ }
+ if ( theBackend != null )
+ {
+ theBackend.acquire();
+ }
+ }
+ return theBackend;
+ }
+
+ public static String [] getSources()
+ {
+ return EnvironmentMgr.getSources( DaemonConfig.getLocalConfig() );
+ }
+
+ public PolicyManager openPolicyMgr( final Properties inProperties,
+ final Name inName )
+ throws APOCException
+ {
+ final String theKey = createPolicyMgrKey( inName );
+ RefCountedPolicyMgr thePolicyMgr = null;
+ synchronized( mPolicyMgrs )
+ {
+ try
+ {
+ thePolicyMgr =
+ ( RefCountedPolicyMgr )mPolicyMgrs.get( theKey );
+ if ( thePolicyMgr == null )
+ {
+ thePolicyMgr =
+ new RefCountedPolicyMgr(
+ inName,
+ inProperties );
+ mPolicyMgrs.put( theKey, thePolicyMgr );
+ }
+ if ( thePolicyMgr != null )
+ {
+ thePolicyMgr.acquire();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ return thePolicyMgr;
+ }
+
+ private PolicyBackendFactory()
+ {
+ }
+
+ private String createPolicyBackendKey( final Name inName )
+ {
+ return inName.toString();
+ }
+
+ private String createPolicyMgrKey( final Name inName )
+ {
+ return inName.getUserName() + Name.sSep + inName.getLocation();
+ }
+
+ class RefCountedPolicyMgr extends PolicyManager
+ {
+ private int mRefCount = 0;
+ private Name mName;
+
+ RefCountedPolicyMgr( final Name inName,
+ final Hashtable inProperties ) throws SPIException
+ {
+ super( inProperties );
+ mName = inName;
+ }
+
+ int acquire() { return ++ mRefCount; }
+ int release() { return -- mRefCount; }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java b/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java
new file mode 100644
index 0000000..f594b25
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java
@@ -0,0 +1,221 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import com.sun.apoc.spi.ldap.authentication.*;
+
+import java.io.IOException;
+import java.nio.*;
+import javax.security.auth.callback.*;
+
+class SaslAuthCallbackHandler implements CallbackHandler
+{
+ private Messenger mMessenger = new Messenger();
+ private ClientChannel mChannel;
+ private ByteBuffer mBuffer;
+ private boolean mReconnectMode = false;
+
+ SaslAuthCallbackHandler( final Client inClient )
+ throws APOCException
+ {
+ mChannel = inClient.getClientChannel();
+ mMessenger.setClientChannel( mChannel );
+ }
+
+ public void handle( Callback[] inCallbacks )
+ throws IOException, UnsupportedCallbackException
+ {
+ final LdapSaslGSSAPICallback theCallback =
+ ( LdapSaslGSSAPICallback )inCallbacks[ 0 ];
+ if ( mBuffer == null )
+ {
+ createTokens( theCallback );
+ }
+ theCallback.setResponse( getToken() );
+ }
+
+ public void setReconnectMode() { mReconnectMode = true; }
+
+ private void createTokens( final LdapSaslGSSAPICallback inCallback )
+ {
+ try
+ {
+ if ( mReconnectMode )
+ {
+ mChannel.registerForSelection( false );
+ }
+ mMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccessContinueSASLAuth,
+ null,
+ new StringBuffer( inCallback.getServiceName() )
+ .append( "/" )
+ .append( inCallback.getHostname() )
+ .toString() ),
+ false );
+ final CredentialsProviderMessage theMessage =
+ ( CredentialsProviderMessage )mMessenger.receiveRequest(
+ ! mReconnectMode );
+
+ if ( theMessage != null )
+ {
+ final String theCreds = theMessage.getCredentials();
+ if ( theCreds != null )
+ {
+ mBuffer =
+ ByteBuffer.wrap(
+ base64ToByteArray( theCreds.toCharArray() ) );
+ }
+ }
+ if ( mReconnectMode )
+ {
+ mMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccess, null, null ),
+ true );
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "SaslAuthCallbackHandler",
+ "createTokens",
+ theException );
+ }
+ }
+
+ private byte[] getToken()
+ {
+ byte[] theToken = null;
+ if ( mBuffer != null && mBuffer.hasRemaining() )
+ {
+ int theTokenSize = nextTokenSize();
+ if ( theTokenSize > 0 )
+ {
+ theToken = new byte[ theTokenSize ];
+ mBuffer = mBuffer.get( theToken );
+ }
+ if ( ! mBuffer.hasRemaining() )
+ {
+ mBuffer = null;
+ }
+ }
+ return theToken;
+ }
+
+ private int nextTokenSize()
+ {
+ int theTokenSize = 0;
+ try
+ {
+ if ( mBuffer.hasRemaining() )
+ {
+ final byte[] theTokenSizeBytes = new byte[ 5 ];
+ mBuffer = mBuffer.get( theTokenSizeBytes );
+ theTokenSize =
+ Integer.parseInt( new String( theTokenSizeBytes ) );
+ }
+ }
+ catch( Exception theException )
+ {}
+ return theTokenSize;
+ }
+
+ // Code borrowed from java.util.prefs.Base64
+ private static final byte base64ToInt[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ private byte[] base64ToByteArray(char[] encoded) {
+ byte[] alphaToInt = base64ToInt;
+ int encodedLen = encoded.length;
+ int numGroups = encodedLen/4;
+ if (4*numGroups != encodedLen)
+ throw new IllegalArgumentException(
+ "String length must be a multiple of four.");
+ int missingBytesInLastGroup = 0;
+ int numFullGroups = numGroups;
+ if (encodedLen != 0) {
+ if (encoded[encodedLen-1] == '=') {
+ missingBytesInLastGroup++;
+ numFullGroups--;
+ }
+ if (encoded[encodedLen-2] == '=')
+ missingBytesInLastGroup++;
+ }
+ byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
+
+ // Translate all full groups from base64 to byte array elements
+ int inCursor = 0, outCursor = 0;
+ for (int i=0; i<numFullGroups; i++) {
+ int ch0 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch1 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch2 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch3 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ result[outCursor++] = (byte) ((ch2 << 6) | ch3);
+ }
+
+ // Translate partial group, if present
+ if (missingBytesInLastGroup != 0) {
+ int ch0 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch1 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+
+ if (missingBytesInLastGroup == 1) {
+ int ch2 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ }
+ }
+ return result;
+ }
+
+ private int base64toInt(char c, byte[] alphaToInt) {
+ int result = alphaToInt[c];
+ if (result < 0)
+ throw new IllegalArgumentException("Illegal character " + c);
+ return result;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Session.java b/src/com/sun/apoc/daemon/apocd/Session.java
new file mode 100644
index 0000000..44d2416
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Session.java
@@ -0,0 +1,335 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.DaemonConfig;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+
+import java.io.*;
+import java.nio.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+
+
+public class Session
+{
+ private Client mClient;
+ private String mSessionId;
+ private HashMap mListeners = new HashMap();
+ private Cache[] mCaches;
+ private Object mLock = new Object();
+ private Hashtable mEntities = null ;
+
+ private static final String sSep = ".";
+ private static final Random sRandom = new Random();
+ private static int sAuthBufferSize = 20;
+ private static int sCantLock = 0;
+ private static int sUnlocked = 1;
+ private static int sLocked = 2;
+ private int mState = sUnlocked;
+
+ Session() {}
+
+ public Session( final Client inClient,
+ final String inUserId,
+ String inEntityName )
+ throws APOCException
+ {
+ Hashtable theEntities = new Hashtable();
+
+ if (inEntityName == null) { inEntityName = inUserId ; }
+ theEntities.put( EnvironmentConstants.USER_SOURCE, inEntityName );
+ initialise( inClient, inUserId, theEntities );
+ }
+ public Session( final Client inClient,
+ final String inUserId,
+ final Hashtable inEntities)
+ throws APOCException
+ {
+ initialise( inClient, inUserId, inEntities );
+ }
+ private void initialise( final Client inClient,
+ final String inUserId,
+ Hashtable inoutEntities) throws APOCException {
+ APOCLogger.finer( "Sess001" );
+ try
+ {
+ authenticate( inClient, inUserId );
+ mClient = inClient;
+ mSessionId = String.valueOf ( sRandom.nextLong() );
+ if (!inoutEntities.containsKey(EnvironmentConstants.HOST_SOURCE)) {
+ String hostName = DaemonConfig.getHostIdentifier() ;
+
+ if (hostName != null) {
+ inoutEntities.put(EnvironmentConstants.HOST_SOURCE,
+ hostName) ;
+ }
+ }
+ mEntities = inoutEntities ;
+ mCaches = CacheFactory
+ .getInstance()
+ .openCaches(
+ inUserId,
+ mEntities,
+ this,
+ new SaslAuthCallbackHandler( mClient ) );
+ }
+ catch( APOCException theException )
+ {
+ close();
+ throw theException;
+ }
+ APOCLogger.finer( "Sess002", toString( inUserId ) );
+ }
+
+ public Cache[] getCaches() { return mCaches; }
+ public Client getClient() { return mClient; }
+ public String getSessionId() { return mSessionId; }
+
+ public void addListeners( final Vector inComponentNames,
+ final String inClientData )
+ {
+ synchronized( mListeners )
+ {
+ for ( int theIndex = 0;
+ theIndex < inComponentNames.size();
+ ++theIndex )
+ {
+ mListeners.put( inComponentNames.elementAt( theIndex ),
+ inClientData );
+ }
+ }
+ }
+
+ public void removeListeners( final Vector inComponentNames )
+ {
+ synchronized( mListeners )
+ {
+ for ( int theIndex = 0;
+ theIndex < inComponentNames.size();
+ ++ theIndex )
+ {
+ mListeners.remove( inComponentNames.elementAt( theIndex ) );
+ }
+ }
+ }
+
+ public void close()
+ {
+ synchronized( mLock )
+ {
+ if ( mState == sLocked )
+ {
+ try
+ {
+ mLock.wait();
+ }
+ catch( Exception e )
+ {}
+ }
+ mState = sCantLock;
+ mLock.notify();
+ }
+ if ( mCaches != null )
+ {
+ CacheFactory.getInstance().closeCaches( mCaches, this );
+ mCaches = null;
+ }
+ if ( mSessionId != null )
+ {
+ APOCLogger.finer( "Sess003", mSessionId );
+ }
+ }
+
+ public String getListenerClientData( final String inComponentName )
+ {
+ return ( String )mListeners.get( inComponentName );
+ }
+
+ public String getListenerComponentName( final String inComponentName )
+ {
+ synchronized( mListeners )
+ {
+ String theComponentName =
+ mListeners.containsKey( inComponentName ) ? inComponentName :
+ null;
+ if ( theComponentName == null )
+ {
+ final StringTokenizer theTokenizer =
+ new StringTokenizer( inComponentName, sSep );
+ final StringBuffer theBuffer = new StringBuffer();
+ int theCount = theTokenizer.countTokens();
+ for ( int theIndex = 0; theIndex < theCount - 1 ; theIndex ++ )
+ {
+ final String theContainerName =
+ theBuffer.append( theTokenizer.nextToken() )
+ .append( sSep )
+ .toString();
+ if ( mListeners.containsKey( theContainerName ) )
+ {
+ theComponentName = theContainerName;
+ break;
+ }
+ }
+ }
+ return theComponentName;
+ }
+ }
+
+ //
+ // lock() & unlock() are provided to support the case where a
+ // change detection transaction and a destroy session transaction are
+ // happening at the same time. lock() will allow a change detection to
+ // continue using the session until it's complete without fear of the
+ // session being closed. Once complete, the change detection transaction
+ // will unlock the session, allowing it to be destroyed.
+ //
+ public boolean lock()
+ {
+ boolean isLocked = false;
+ synchronized( mLock )
+ {
+ if ( mState == sUnlocked )
+ {
+ mState = sLocked;
+ isLocked = true;
+ }
+ }
+ return isLocked;
+ }
+
+ public void unlock()
+ {
+ synchronized( mLock )
+ {
+ mState = sUnlocked;
+ mLock.notify();
+ }
+ }
+
+ public void sendNotification(UpdateItem aUpdate) {
+ String component = aUpdate.getComponentName() ;
+ String listenerComponent = getListenerComponentName(component) ;
+
+ if (listenerComponent == null) { return ; }
+ int notificationType = -1 ;
+ StringBuffer logMessage = new StringBuffer(" sessionId = ")
+ .append(mSessionId).append("\n")
+ .append(" component name = ")
+ .append(component).append("\n")
+ .append(" type = ") ;
+
+ switch (aUpdate.getUpdateType()) {
+ case UpdateItem.ADD:
+ notificationType = APOCSymbols.sSymAddNotification ;
+ logMessage.append("Add") ;
+ break ;
+ case UpdateItem.REMOVE:
+ notificationType = APOCSymbols.sSymRemoveNotification ;
+ logMessage.append("Remove") ;
+ break ;
+ case UpdateItem.MODIFY:
+ notificationType = APOCSymbols.sSymModifyNotification ;
+ logMessage.append("Modify") ;
+ break ;
+ default:
+ notificationType = -1 ;
+ logMessage.append("Unknown") ;
+ break ;
+ }
+ APOCLogger.finer("Cdtn003", logMessage.toString()) ;
+ final Notification notification =
+ (Notification) MessageFactory.createNotification(mSessionId,
+ notificationType) ;
+
+ notification.setComponentName(component) ;
+ notification.setClientData(getListenerClientData(listenerComponent)) ;
+ mClient.getClientChannel().write(notification.serialise()) ;
+ }
+
+ private void authenticate( final Client inClient,
+ final String inUserId )
+ throws APOCException
+ {
+ APOCAuthenticator theAuthenticator = null;
+ try
+ {
+ theAuthenticator = new APOCAuthenticator( inUserId );
+ final Messenger theMessenger = new Messenger();
+ theMessenger.setClientChannel( inClient.getClientChannel() );
+ theMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccessContinueLocalAuth,
+ null,
+ new String( theAuthenticator.getChallenge() ) ),
+ false );
+ final CredentialsProviderMessage theMessage =
+ ( CredentialsProviderMessage )theMessenger.receiveRequest();
+ theAuthenticator.processResponse(
+ theMessage.getCredentials().getBytes() );
+ }
+ finally
+ {
+ if ( theAuthenticator != null )
+ {
+ theAuthenticator.cleanup();
+ }
+ }
+ }
+
+ private String toString( final String inUserId )
+ {
+ StringBuffer theMessage = new StringBuffer()
+ .append( " userId = " )
+ .append( inUserId )
+ .append( "\n" )
+
+ .append( " sessionId = ")
+ .append( mSessionId )
+ .append( "\n" );
+ for ( int theIndex = 0 ; theIndex < mCaches.length ; ++ theIndex )
+ {
+ theMessage.append( mCaches[ theIndex ].toString() ).append( "\n ");
+ }
+ return theMessage.toString();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/SessionListener.java b/src/com/sun/apoc/daemon/apocd/SessionListener.java
new file mode 100644
index 0000000..3648b92
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/SessionListener.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+public interface SessionListener
+{
+ void onSessionCreate( final Session inSession );
+
+ void onSessionDestroy( final Session inSession );
+}
diff --git a/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java b/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java
new file mode 100644
index 0000000..a51b058
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd ;
+
+import com.sun.apoc.daemon.localdatabase.UpdateItem ;
+
+import java.util.ArrayList ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+public class UpdateAggregator {
+ // Key = session, value = updates
+ private Map mUpdates = new HashMap() ;
+
+ public synchronized void addUpdate(Session [] aSessions,
+ UpdateItem aUpdate) {
+ for (int i = 0 ; i < aSessions.length ; ++ i) {
+ Session session = aSessions [i] ;
+
+ if (!mUpdates.containsKey(session)) {
+ ArrayList updateList = new ArrayList() ;
+
+ updateList.add(aUpdate) ;
+ mUpdates.put(session, updateList) ;
+ }
+ else {
+ ArrayList updateList = (ArrayList) mUpdates.get(session) ;
+
+ for (int j = 0 ; j < updateList.size() ; ++ j) {
+ UpdateItem update = (UpdateItem) updateList.get(j) ;
+
+ if (update.getComponentName().equals(
+ aUpdate.getComponentName())) {
+ if (update.getUpdateType() != aUpdate.getUpdateType()) {
+ update.setUpdateType(UpdateItem.MODIFY) ;
+ }
+ return ;
+ }
+ }
+ updateList.add(aUpdate) ;
+ }
+ }
+ }
+ public void sendNotifications() {
+ Iterator updates = mUpdates.entrySet().iterator() ;
+
+ while (updates.hasNext()) {
+ Map.Entry update = (Map.Entry) updates.next();
+ Session session = (Session) update.getKey() ;
+ ArrayList updateList = (ArrayList) update.getValue() ;
+ int nbUpdates = updateList.size() ;
+
+ for (int i = 0 ; i < nbUpdates ; ++ i) {
+ session.sendNotification((UpdateItem) updateList.get(i)) ;
+ }
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/build.xml.in b/src/com/sun/apoc/daemon/build.xml.in
new file mode 100644
index 0000000..0ddc898
--- /dev/null
+++ b/src/com/sun/apoc/daemon/build.xml.in
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+#*************************************************************************
+#*
+#* $RCSfile: build.xml,v $
+#*
+#* Creation date cas 12 February, 2002
+#* last change $Author: cm122549 $ $Date: 2006/11/27 15:42:26 $
+#* $Revision: 1.4 $
+#*
+#* Copyright 2003, Sun Microsystems, Inc. All Rights Reserved.
+#*
+#*************************************************************************
+-->
+<project name="ap_policy" default="main" basedir="../../../../../">
+
+ <property name="jarname" value="apocd.jar"/>
+ <property name="package" value="com/sun/apoc/daemon"/>
+ <property name="build.dir" value="build"/>
+ <property name="build.class" value="build/class"/>
+ <property name="build.inc" value="build/inc"/>
+
+ <target name="info">
+ <echo message="-------------------------------"/>
+ <echo message="| APOC Daemon |"/>
+ <echo message="-------------------------------"/>
+ </target>
+
+ <path id="classpath">
+ <pathelement location="@SPIJDK@"/>
+ <pathelement location="@BDBJDK@"/>
+ </path>
+
+ <target name="prepare">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <target name="compile" depends="prepare">
+ <javac srcdir="src"
+ destdir="${build.class}"
+ optimize="${optimize}"
+ debug="${debug}"
+ classpathref="classpath">
+ <include name="${package}/**/*.java"/>
+ </javac>
+ </target>
+
+ <target name="jar" depends="compile">
+ <condition property="dataDir" value="@APOC_DATADIR@">
+ <os name="SunOS"/>
+ </condition>
+ <condition property="dataDir" value="@APOC_DATADIR@">
+ <os name="Linux"/>
+ </condition>
+ <condition property="dataDir" value="\\Documents and Settings\\All Users\\Application Data\\apoc">
+ <os family="Windows"/>
+ </condition>
+
+ <copy file="src/${package}/properties/defaults.properties"
+ tofile="${build.class}/${package}/defaults.properties"/>
+ <copy file="src/${package}/properties/os.properties" filtering="true"
+ tofile="${build.class}/${package}/os.properties">
+ <filterset>
+ <filter token="DataDir" value="${dataDir}"/>
+ </filterset>
+ </copy>
+ <copy file="src/${package}/properties/daemon.properties"
+ tofile="${build.class}/com/sun/apoc/daemon.properties"/>
+
+ <jar jarfile="${build.class}/${jarname}"
+ basedir="${build.class}"
+ includes="${package}/** ${package}/defaults.properties ${package}/os.properties com/sun/apoc/daemon.properties">
+ <manifest>
+ <attribute name="Class-Path" value="@SPIJDK@ @BDBJDK@"/>
+ </manifest>
+ </jar>
+ </target>
+
+ <target name="main" depends="info, jar"/>
+
+ <target name="clean" depends="info">
+ <delete file="${build.class}/${jarname}"/>
+ <delete dir="${build.class}/${package}"/>
+ </target>
+
+</project>
diff --git a/src/com/sun/apoc/daemon/config/ConfigEventListener.java b/src/com/sun/apoc/daemon/config/ConfigEventListener.java
new file mode 100644
index 0000000..52e31fb
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/ConfigEventListener.java
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+public interface ConfigEventListener
+{
+ public void onConfigEvent();
+}
diff --git a/src/com/sun/apoc/daemon/config/DaemonConfig.java b/src/com/sun/apoc/daemon/config/DaemonConfig.java
new file mode 100644
index 0000000..639d712
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/DaemonConfig.java
@@ -0,0 +1,418 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.spi.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+import java.util.zip.*;
+
+public class DaemonConfig implements ConfigEventListener
+{
+ // Public bootstrap properties
+ public static final String sDaemonPort = "DaemonPort";
+ public static final String sDataDir = "DataDir";
+
+ // Non bootstrap
+ public static final String sMaxClientThreads =
+ "MaxClientThreads";
+ public static final String sMaxClientConnections =
+ "MaxClientConnections";
+ public static final String sMaxRequestSize =
+ "MaxRequestSize";
+ public static final String sConfigCDInterval =
+ "DaemonChangeDetectionInterval";
+ public static final String sChangeDetectionInterval =
+ "ChangeDetectionInterval";
+ public static final String sGarbageCollectionInterval =
+ "GarbageCollectionInterval";
+ public static final String sTimeToLive =
+ "TimeToLive";
+ public static final String sLogLevel =
+ "LogLevel";
+ public static final String sIdleThreadDetectionInterval =
+ "IdleThreadDetectionInterval";
+ public static final String sThreadTimeToLive =
+ "ThreadTimeToLive";
+ public static final String sConnectionReadTimeout =
+ "ConnectionReadTimeout";
+ public static final String sInitialChangeDetectionDelay =
+ "InitialChangeDetectionDelay";
+ public static final String sApplyLocalPolicy =
+ "ApplyLocalPolicy";
+ public static final String sMaxDbLocks =
+ "MaxDatabaseLocks";
+ private static DaemonConfig sInstance;
+
+ private static final String sAPOCJarFile = "apocd.jar";
+ private static final String sDefaultsPropertiesFile = "defaults.properties";
+ public static final String sOSPropertiesFile = "os.properties";
+ public static final String sApocPropertiesFile = "apocd.properties";
+ public static final String sJProxyPropertiesFile = "policymgr.properties";
+ private static final String[] sLocalPropertiesFiles =
+ { sOSPropertiesFile, sApocPropertiesFile, sJProxyPropertiesFile };
+ private static String sDaemonInstallDir;
+ private static String sDaemonPropertiesDir;
+
+ private Properties mDefaultProperties;
+ private RemoteConfig mRemoteConfig;
+ private LocalConfig mLocalConfig;
+ private final HashSet mConfigEventListeners = new HashSet();
+ private String mHostIdentifier;
+ private final DaemonTimerTask mConfigLoader =
+ new DaemonTimerTask( new ConfigLoader() );
+
+ public static void addConfigEventListener(
+ final ConfigEventListener inConfigListener )
+ {
+ synchronized( sInstance.mConfigEventListeners )
+ {
+ sInstance.mConfigEventListeners.add( inConfigListener );
+ }
+ }
+
+ static public String getHostIdentifier()
+ {
+ return sInstance.mHostIdentifier;
+ }
+
+ public static DaemonConfig getInstance()
+ {
+ return sInstance;
+ }
+
+ public static boolean getBooleanProperty( final String inPropertyName )
+ {
+ return getBooleanProperty( inPropertyName, null );
+ }
+
+ public static boolean getBooleanProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Boolean.valueOf(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() ).
+ booleanValue();
+ }
+
+ public static float getFloatProperty( final String inPropertyName )
+ {
+ return getFloatProperty( inPropertyName, null );
+ }
+
+ public static float getFloatProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Float.parseFloat(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() );
+ }
+
+ public static int getIntProperty( final String inPropertyName )
+ {
+ return getIntProperty( inPropertyName, null );
+ }
+
+ public static int getIntProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Integer.parseInt(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() );
+ }
+
+ public static LocalConfig getLocalConfig()
+ {
+ return sInstance.mLocalConfig;
+ }
+
+ public static String getStringProperty( final String inPropertyName )
+ {
+ return getStringProperty( inPropertyName, null );
+ }
+
+ public static String getStringProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return sInstance.mLocalConfig.getProperty( inPropertyName,
+ inDefaultValue );
+ }
+
+ public static void init( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ sInstance = new DaemonConfig( inArgs );
+ reload();
+ addConfigEventListener( sInstance );
+ sInstance.pollForChanges();
+ }
+
+ public static void log()
+ {
+ if ( APOCLogger.isLoggable( Level.CONFIG ) &&
+ sInstance != null &&
+ sInstance.mLocalConfig != null )
+ {
+ final StringBuffer theBuffer = new StringBuffer( "" );
+ final Enumeration theEnumeration =
+ sInstance.mLocalConfig.propertyNames();
+ while ( theEnumeration.hasMoreElements() )
+ {
+ final String theName = ( String )theEnumeration.nextElement();
+ theBuffer.append( " " )
+ .append( theName )
+ .append( " = " )
+ .append(
+ theName.compareTo( "Password" ) == 0 ?
+ obscure(
+ DaemonConfig.getStringProperty( theName ) ):
+ DaemonConfig.getStringProperty( theName ) )
+ .append( "\n" );
+ }
+ APOCLogger.config( "Dcfg001", theBuffer.toString() );
+ }
+ }
+
+ public void onConfigEvent()
+ {
+ pollForChanges();
+ }
+
+ public static void reload()
+ throws IOException
+ {
+ reload( false );
+ }
+
+ public static void reload( boolean inRemoteOnly )
+ throws IOException
+ {
+ final Set theOriginalValues = sInstance.getAllValues();
+ if ( ! inRemoteOnly )
+ {
+ sInstance.mLocalConfig.load( sLocalPropertiesFiles );
+ sInstance.setHostIdentifier();
+ }
+ sInstance.mRemoteConfig.load();
+ if ( ! sInstance.getAllValues().equals( theOriginalValues ) )
+ {
+ sInstance.configLoaded();
+ }
+ }
+
+ public static void removeConfigEventListener(
+ final ConfigEventListener inConfigListener)
+ {
+ synchronized( sInstance.mConfigEventListeners )
+ {
+ sInstance.mConfigEventListeners.remove( inConfigListener );
+ }
+ }
+
+ private DaemonConfig( final String[] inArgs )
+ throws IOException
+ {
+ sDaemonInstallDir = inArgs[ 0 ];
+ sDaemonPropertiesDir = inArgs[ 1 ];
+ createDefaults();
+ mLocalConfig = new LocalConfig( sDaemonPropertiesDir );
+ mRemoteConfig = new RemoteConfig();
+ mLocalConfig.setDefaults( mRemoteConfig );
+ mRemoteConfig.setDefaults( mDefaultProperties );
+ }
+
+ private void configLoaded()
+ {
+ Object[] theConfigEventListeners;
+ synchronized( mConfigEventListeners )
+ {
+ theConfigEventListeners = mConfigEventListeners.toArray();
+ }
+ if ( theConfigEventListeners != null )
+ {
+ for ( int theIndex = 0;
+ theIndex < theConfigEventListeners.length;
+ ++ theIndex )
+ {
+ ( ( ConfigEventListener )theConfigEventListeners[ theIndex ] )
+ .onConfigEvent();
+ }
+ }
+ }
+
+ private void createDefaults()
+ throws IOException
+ {
+ ZipFile theZipFile =
+ new ZipFile(
+ new StringBuffer( sDaemonInstallDir )
+ .append( File.separatorChar )
+ .append( sAPOCJarFile )
+ .toString() );
+
+ String thePath = new String( "com/sun/apoc/daemon/" );
+
+ mDefaultProperties = new Properties();
+ mDefaultProperties.load(
+ theZipFile.getInputStream(
+ theZipFile.getEntry(
+ new StringBuffer( thePath )
+ .append( sDefaultsPropertiesFile )
+ .toString() ) ) );
+
+ mDefaultProperties.load(
+ theZipFile.getInputStream(
+ theZipFile.getEntry(
+ new StringBuffer( thePath )
+ .append( sOSPropertiesFile )
+ .toString() ) ) );
+ }
+
+ private Set getAllValues()
+ {
+ final HashSet theSet = new HashSet();
+ if ( mLocalConfig != null )
+ {
+ final Enumeration theEnumeration = mLocalConfig.propertyNames();
+ while ( theEnumeration.hasMoreElements() )
+ {
+ theSet.add(
+ mLocalConfig.getProperty(
+ ( String )theEnumeration.nextElement() ) );
+ }
+ }
+ return theSet;
+ }
+
+ /**
+ * Check if the address can be used to identify the machine from
+ * an external point of view. For the moment limited to checking
+ * that it's not the loopback address.
+ */
+ private static boolean isAcceptableAddress(InetAddress inAddress) {
+ return !inAddress.isLoopbackAddress() ;
+ }
+
+ private String guessHostIdentifer()
+ {
+ String theHostIdentifier = null;
+ try
+ {
+ Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
+ if ( theInterfaces != null )
+ {
+ while ( theInterfaces.hasMoreElements() )
+ {
+ NetworkInterface theInterface =
+ ( NetworkInterface )theInterfaces.nextElement();
+ Enumeration theInetAddresses=
+ theInterface.getInetAddresses();
+ if ( theInetAddresses != null )
+ {
+ while ( theInetAddresses.hasMoreElements() )
+ {
+ InetAddress theAddress =
+ ( InetAddress )theInetAddresses.nextElement();
+ if (isAcceptableAddress(theAddress))
+ {
+ theHostIdentifier = theAddress.getHostAddress();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( Exception theException ){}
+ return theHostIdentifier;
+ }
+
+ private static String obscure( final String inString )
+ {
+ String theString = null;
+ if ( inString != null )
+ {
+ theString = inString.replaceAll( "\\p{Alnum}", "*" );
+ }
+ return theString;
+ }
+
+ private void pollForChanges()
+ {
+ mConfigLoader.setPeriod( 60000 * getIntProperty( sConfigCDInterval ) );
+ }
+
+ private void setHostIdentifier()
+ {
+ try
+ {
+ if ( mLocalConfig.getProperty( "HostIdentifierType", "Hostname" )
+ .compareTo( "IPAddress" ) == 0 )
+ {
+ InetAddress theLocalHost = InetAddress.getLocalHost() ;
+ if (isAcceptableAddress(theLocalHost))
+ {
+ mHostIdentifier = theLocalHost.getHostAddress() ;
+ }
+ else
+ {
+ mHostIdentifier = guessHostIdentifer();
+ }
+ }
+ else
+ {
+ mHostIdentifier = InetAddress.getLocalHost().getHostName();
+ }
+ }
+ catch( UnknownHostException theException )
+ {
+ mHostIdentifier = null;
+ }
+ }
+
+ class ConfigLoader implements Runnable
+ {
+ public void run()
+ {
+ try
+ {
+ sInstance.reload( true );
+ }
+ catch( IOException theException )
+ {}
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/config/LocalConfig.java b/src/com/sun/apoc/daemon/config/LocalConfig.java
new file mode 100644
index 0000000..26c8e65
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/LocalConfig.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import java.io.*;
+import java.util.*;
+
+class LocalConfig extends Properties
+{
+ private String mPropertiesDir;
+
+ public LocalConfig( final String inPropertiesDir )
+ {
+ super();
+ mPropertiesDir =
+ new StringBuffer( inPropertiesDir )
+ .append( File.separatorChar )
+ .toString();
+ }
+
+ public void load ( final String[] inFileNames )
+ {
+ clear();
+ for ( int theIndex = 0; theIndex < inFileNames.length; theIndex ++ )
+ {
+ load( inFileNames[ theIndex ] );
+ }
+ }
+
+ public void setDefaults( final Properties inDefaults )
+ {
+ defaults = inDefaults;
+ }
+
+ private void load( final String inFileName )
+ {
+ try
+ {
+ load(
+ new FileInputStream(
+ new StringBuffer( mPropertiesDir )
+ .append( inFileName )
+ .toString() ) );
+ }
+ catch( IOException theException ) {}
+ }
+}
diff --git a/src/com/sun/apoc/daemon/config/RemoteConfig.java b/src/com/sun/apoc/daemon/config/RemoteConfig.java
new file mode 100644
index 0000000..b3935f9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/RemoteConfig.java
@@ -0,0 +1,198 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.cfgtree.*;
+import com.sun.apoc.spi.cfgtree.property.*;
+import com.sun.apoc.spi.cfgtree.policynode.*;
+import com.sun.apoc.spi.cfgtree.readwrite.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.policies.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.util.*;
+
+class RemoteConfig extends Properties
+{
+ private static final String sParentNodeName = "com.sun.apoc.apocd";
+
+ public void load()
+ {
+ clear();
+ PolicyManager thePolicyMgr = null;
+ try
+ {
+ final Properties theProperties =
+ ( Properties )DaemonConfig.getLocalConfig().clone();
+ theProperties.put( EnvironmentConstants.LDAP_AUTH_TYPE_KEY,
+ EnvironmentConstants.LDAP_AUTH_TYPE_ANONYMOUS );
+ thePolicyMgr = new PolicyManager( theProperties );
+ load( thePolicyMgr );
+ }
+ catch ( Exception theException )
+ {}
+ finally
+ {
+ if ( thePolicyMgr != null )
+ {
+ try
+ {
+ thePolicyMgr.close();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "RemoteConfig", "load", theException );
+ }
+ }
+ }
+ }
+
+ public void setDefaults( final Properties inProperties )
+ {
+ defaults = inProperties;
+ }
+
+ private String getPropertyValue( final PolicyNode inParentNode,
+ final String inPropertyName )
+ {
+ String theValue = null;
+ if ( inParentNode != null )
+ {
+ final Property theProperty =
+ inParentNode.getProperty( inPropertyName );
+ if ( theProperty != null )
+ {
+ try
+ {
+ theValue = theProperty.getValue();
+ }
+ catch( SPIException theException ){}
+ }
+ }
+ return theValue;
+ }
+
+ private void load( final PolicyManager inPolicyMgr )
+ throws SPIException
+ {
+ final Entity theDomain =
+ inPolicyMgr.getRootEntity( EnvironmentConstants.HOST_SOURCE );
+ final Iterator theIterator = ((Domain) theDomain).findEntities(
+ DaemonConfig.getHostIdentifier(),
+ true );
+ if ( theIterator != null && theIterator.hasNext() )
+ {
+ final Entity theEntity = ( Entity )theIterator.next();
+ final Iterator theProfiles = theEntity.getLayeredProfiles();
+ if ( theProfiles != null )
+ {
+ final ArrayList thePolicies = new ArrayList();
+ while ( theProfiles.hasNext() )
+ {
+ final Profile theProfile = ( Profile )theProfiles.next();
+ final Policy thePolicy =
+ theProfile.getPolicy( sParentNodeName);
+ if ( thePolicy != null )
+ {
+ thePolicies.add( thePolicy );
+ }
+ }
+ if ( thePolicies.size() > 0 )
+ {
+ final PolicyTree theTree =
+ new ReadWritePolicyTreeFactoryImpl()
+ .getPolicyTree( thePolicies.iterator() );
+ if ( theTree != null )
+ {
+ final PolicyNode theParentNode =
+ theTree.getNode( sParentNodeName );
+ if ( theParentNode != null )
+ {
+ setProp( DaemonConfig.sMaxClientThreads,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxClientThreads ) );
+ setProp( DaemonConfig.sMaxClientConnections,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxClientConnections ) );
+ setProp( DaemonConfig.sMaxRequestSize,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxRequestSize ) );
+ setProp( DaemonConfig.sConfigCDInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sConfigCDInterval ) );
+ setProp( DaemonConfig.sChangeDetectionInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sChangeDetectionInterval ) );
+ setProp( DaemonConfig.sGarbageCollectionInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sGarbageCollectionInterval ) );
+ setProp( DaemonConfig.sTimeToLive,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sTimeToLive ) );
+ setProp( DaemonConfig.sLogLevel,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sLogLevel ) );
+ setProp( DaemonConfig.sApplyLocalPolicy,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sApplyLocalPolicy ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void setProp( final String inPropertyName,
+ final String inPropertyValue )
+ {
+ if ( inPropertyValue != null )
+ {
+ setProperty( inPropertyName, inPropertyValue );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/Database.java b/src/com/sun/apoc/daemon/localdatabase/Database.java
new file mode 100644
index 0000000..6470c6c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/Database.java
@@ -0,0 +1,365 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Database extends Db
+{
+ protected final Name mName;
+ private Dbc mDbc;
+
+ private static final int sDbType = Db.DB_BTREE;
+ private static final int sDbFlags = Db.DB_CREATE;
+ private static final int sDbMode = 0600;
+ private static final String sValueEpoch = "19700101000000Z";
+
+ public static final String sKeyLastChangeDetect = "lastChangeDetect";
+ public static final String sKeyLastModified = "lastModified/";
+ public static final String sKeyLastRead = "lastRead";
+ public static final String sKeyLayerIds = "layerIds/";
+ public static final String sKeyDBs = "dbs";
+ public static final String sKeyRemoteComponentList =
+ "remoteComponentList";
+ public static final String sKeyLocalComponentList =
+ "localComponentList";
+
+ public Database( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super( LocalDatabaseFactory.getInstance(), 0 );
+ mName = inName;
+ openDatabase( LocalDatabaseFactory.getLocalDatabaseFileName(mName),
+ getDatabaseName(mName));
+ }
+
+ public Database(final Name inName, final String inFileName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super(LocalDatabaseFactory.getInstance(), 0) ;
+ mName = inName ;
+ openDatabase(inFileName, getDatabaseName(mName)) ;
+ }
+ private void openDatabase(final String inFileName,
+ final String inDatabaseName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ open(null, inFileName, inDatabaseName, sDbType, sDbFlags, sDbMode) ;
+ }
+
+ public Name getName() { return mName; }
+
+ public static String getDatabaseName(Name aName)
+ {
+ return new StringBuffer(aName.getEntityType()).append(Name.sSep)
+ .append(aName.getEntityName()).append(Name.sSep)
+ .append(aName.getLocation()).toString() ;
+ }
+
+ public static Database createDatabase(String aName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ String [] components = aName.split(Name.sSep) ;
+
+ if (components != null && components.length > 2)
+ {
+ return new Database(new Name(null,
+ components [0],
+ components [1],
+ components [2])) ;
+ }
+ throw new APOCException() ;
+ }
+
+ public String toString() { return getDatabaseName(mName) ; }
+
+ public void beginTransaction()
+ throws APOCException
+ {
+ try
+ {
+ final Dbc theCursor = cursor( null, Db.DB_WRITECURSOR );
+ mDbc = theCursor;
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void endTransaction()
+ throws APOCException
+ {
+ if ( mDbc != null )
+ {
+ try
+ {
+ final Dbc theCursor = mDbc;
+ mDbc = null;
+ theCursor.close();
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ }
+
+ public int get( String inKey, final Dbt outValue )
+ throws APOCException
+ {
+ return get( new StringDbt( inKey ), outValue );
+ }
+
+ public int get( final Dbt inKey, final Dbt outValue )
+ throws APOCException
+ {
+ try
+ {
+ return get( null, inKey, outValue, 0 );
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public HashSet getDBList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyDBs, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public String getLastChangeDetect()
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( sKeyLastChangeDetect, theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLastModified( final String inLayerId,
+ final String inComponentName )
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( new StringBuffer( sKeyLastModified )
+ .append( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString(),
+ theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLastRead()
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( sKeyLastRead, theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLayer( final String inComponentName,
+ final String inLayerId )
+ throws APOCException
+ {
+ final String theKey = new StringBuffer( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString();
+ StringDbt theValue = new StringDbt();
+ get( theKey, theValue );
+ return theValue.getApocData();
+ }
+
+ public Vector getLayerIds( final String inComponentName )
+ throws APOCException
+ {
+ final VectorStringDbt theVectorDbt = new VectorStringDbt();
+ get( new StringBuffer( sKeyLayerIds )
+ .append( inComponentName )
+ .toString(),
+ theVectorDbt );
+ return theVectorDbt.retrieveData();
+ }
+
+ public HashSet getLocalComponentList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyLocalComponentList, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public HashSet getRemoteComponentList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyRemoteComponentList, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public int put( final Dbt inKey, final String inData )
+ throws APOCException
+ {
+ return put( inKey, new StringDbt( inData ) );
+ }
+
+ public int put( final String inKey, final HashSet inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), new SetDbt( inData ) );
+ }
+
+ public int put( final Dbt inKey, final HashSet inData )
+ throws APOCException
+ {
+ return put( inKey, new SetDbt( inData ) );
+ }
+
+ public int put(final String inKey, final Vector inData)
+ throws APOCException
+ {
+ return put(new StringDbt(inKey), new VectorStringDbt(inData)) ;
+ }
+
+ public int put( final String inKey, final String inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), new StringDbt( inData ) );
+ }
+
+ public int put( final String inKey, final Dbt inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), inData );
+ }
+
+ public int put( final Dbt inKey, final Dbt inData )
+ throws APOCException
+ {
+ try
+ {
+ return mDbc.put( inKey, inData, Db.DB_KEYFIRST );
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void putDBList( final HashSet inDBList )
+ throws APOCException
+ {
+ put( sKeyDBs, inDBList );
+ }
+
+ public void putLastChangeDetect( final String inTimestamp )
+ throws APOCException
+ {
+ put( sKeyLastChangeDetect, inTimestamp );
+ }
+
+ public void putLastModified( final String inLayerId,
+ final String inComponentName,
+ final String inTimestamp )
+ throws APOCException
+ {
+ put( new StringBuffer( sKeyLastModified )
+ .append( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString(),
+ inTimestamp );
+ }
+
+ public void putLayerIds( final String inComponentName,
+ final Vector inLayerIds )
+ throws APOCException
+ {
+ put ( new StringBuffer( sKeyLayerIds )
+ .append( inComponentName )
+ .toString(),
+ inLayerIds );
+ }
+
+ public void putRemoteComponentList( final HashSet inRemoteComponentList )
+ throws APOCException
+ {
+ put( sKeyRemoteComponentList, inRemoteComponentList );
+ }
+
+ public void putLocalComponentList( final HashSet inComponentNames )
+ throws APOCException
+ {
+ put( sKeyLocalComponentList, inComponentNames );
+ }
+
+ protected void putLastRead()
+ throws APOCException
+ {
+ put( sKeyLastRead, Timestamp.getTimestamp() );
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java b/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java
new file mode 100644
index 0000000..6154dff
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java
@@ -0,0 +1,200 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.policies.*;
+
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+
+public class LocalDatabase extends Database
+{
+ private HashSet mLocalComponentList;
+ private int mRefCount = 0;
+
+ public LocalDatabase( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super( inName );
+ initLocalComponentList();
+ }
+
+ synchronized public int acquire() { return ++mRefCount; }
+ synchronized public int release()
+ {
+ if ( --mRefCount == 0 )
+ {
+ try
+ {
+ beginTransaction();
+ putLastRead();
+ endTransaction();
+ close( 0 );
+ }
+ catch( DbException theException )
+ {}
+ catch( APOCException theException )
+ {}
+ }
+ return mRefCount;
+ }
+
+ public boolean hasComponent( final String inComponentName )
+ {
+ return mLocalComponentList.contains( inComponentName );
+ }
+
+ public void putLocalComponentList( final HashSet inLocalComponentList )
+ throws APOCException
+ {
+ mLocalComponentList = inLocalComponentList;
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ public void update( final UpdateItem inUpdateItem, final String inTimestamp)
+ throws APOCException
+ {
+ if ( inUpdateItem != null )
+ {
+ updateItem( inUpdateItem, new StringDbt( inTimestamp ) );
+ }
+ }
+
+ public void update( final ArrayList inUpdateItems, final String inTimestamp)
+ throws APOCException
+ {
+ int theSize;
+ if ( inUpdateItems != null && ( theSize = inUpdateItems.size() ) > 0 )
+ {
+ StringDbt theTimestamp = new StringDbt( inTimestamp );
+ for ( int theIndex = 0; theIndex < theSize; ++ theIndex )
+ {
+ updateItem( ( UpdateItem )inUpdateItems.get( theIndex ),
+ theTimestamp );
+ }
+ }
+ }
+
+ private void addLocalComponent( final String inComponentName )
+ throws APOCException
+ {
+ mLocalComponentList.add( inComponentName );
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ private void initLocalComponentList()
+ throws APOCException
+ {
+ if ( ( mLocalComponentList = super.getLocalComponentList() ) == null )
+ {
+ mLocalComponentList = new HashSet();
+ }
+ }
+
+ private void putComponent( final String inComponentName,
+ final Policy[] inPolicies )
+ throws APOCException
+ {
+ if ( inPolicies != null && inPolicies.length > 0 )
+ {
+ final Vector theLayerIds = new Vector( inPolicies.length );
+ for ( int theIndex = 0; theIndex < inPolicies.length; theIndex ++ )
+ {
+ final String theLayerId =
+ String.valueOf(
+ inPolicies[ theIndex].getProfileId().hashCode() );
+
+ String theKey = new StringBuffer( theLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString();
+ put( theKey, inPolicies[ theIndex ].getData() );
+
+ theLayerIds.add( theLayerId );
+
+ putLastModified( theLayerId,
+ inComponentName,
+ Timestamp.getTimestamp(
+ inPolicies[ theIndex ].getLastModified() ));
+ }
+ putLayerIds( inComponentName, theLayerIds );
+ }
+ }
+
+ private void removeLocalComponent( final String inComponentName )
+ throws APOCException
+ {
+ mLocalComponentList.remove( inComponentName );
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ private void updateItem( final UpdateItem inUpdateItem )
+ throws APOCException
+ {
+ updateItem( inUpdateItem, new StringDbt( Timestamp.getTimestamp() ) );
+ }
+
+ private void updateItem( final UpdateItem inUpdateItem,
+ final Dbt inTimestamp )
+ throws APOCException
+ {
+ String theComponentName = inUpdateItem.getComponentName();
+ Policy[] thePolicies = inUpdateItem.getPolicies();
+ switch ( inUpdateItem.getUpdateType() )
+ {
+ case UpdateItem.ADD:
+ putComponent( theComponentName, thePolicies );
+ addLocalComponent( theComponentName );
+ break;
+
+ case UpdateItem.MODIFY:
+ putComponent( theComponentName, thePolicies );
+ break;
+
+ case UpdateItem.REMOVE:
+ removeLocalComponent( theComponentName );
+ break;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java b/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java
new file mode 100644
index 0000000..13ae22b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java
@@ -0,0 +1,460 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+public class LocalDatabaseFactory extends DbEnv
+{
+ private static LocalDatabaseFactory sInstance;
+ private static final HashMap sDatabases =
+ new HashMap( DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections ) );
+ private static final String sLDBHome =
+ new StringBuffer(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( File.separatorChar )
+ .append( "LocalDB" )
+ .toString();
+ private static final Name sDbListDbName =
+ new Name(null, "DbListType", "DbList", true) ;
+
+
+ private static final int sDbEnvFlags = Db.DB_CREATE |
+ Db.DB_INIT_CDB |
+ Db.DB_INIT_MPOOL |
+ Db.DB_PRIVATE;
+
+ private static final int sDbEnvMode = 0600;
+ private static final String s__dbPrefix = "__db.";
+
+ private LocalDatabaseFactory()
+ throws APOCException, DbException
+ {
+ super( 0 );
+ createDBHome();
+ initLocks();
+ openEnv();
+ }
+
+ public void deleteDatabase( final Database inDatabase )
+ {
+ final Name theName = inDatabase.getName();
+ synchronized ( sDatabases )
+ {
+ if ( ! sDatabases.containsKey( createDatabaseKey( theName ) ) )
+ {
+ try
+ {
+ final HashSet theDBs = removeDbFromDbList( theName );
+ if ( theDBs == null || theDBs.size() == 0 )
+ {
+ new File(getLocalDatabaseFilePath(theName)).delete() ;
+ }
+ }
+ catch( Exception theException )
+ {}
+ }
+ }
+ }
+ public static LocalDatabaseFactory getInstance()
+ throws APOCException
+ {
+ if ( sInstance == null )
+ {
+ try
+ {
+ sInstance = new LocalDatabaseFactory();
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ public void run() {
+ try {
+ Iterator databases =
+ sDatabases.values().iterator() ;
+
+ while (databases.hasNext()) {
+ ((Database) databases.next()).close(0) ;
+ }
+ sInstance.close(0) ;
+ }
+ catch (DbException ignored) {}
+ }
+ })) ;
+
+ }
+ catch ( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ return sInstance;
+ }
+
+ public Object[] getDatabases()
+ {
+ Object[] theDatabases = null;
+ final String[] theDBFileNames = new File( sLDBHome ).list();
+ if ( theDBFileNames != null )
+ {
+ final ArrayList theDBList = new ArrayList( theDBFileNames.length );
+ for ( int theIndex = 0;
+ theIndex < theDBFileNames.length;
+ ++ theIndex )
+ {
+ if ( theDBFileNames[ theIndex ].startsWith( s__dbPrefix ) )
+ {
+ continue;
+ }
+ String[] theNames =
+ getDatabaseNames( theDBFileNames[ theIndex ] );
+ if ( theNames != null )
+ {
+ for ( int theNamesIndex = 0;
+ theNamesIndex < theNames.length;
+ ++ theNamesIndex )
+ {
+ synchronized( sDatabases )
+ {
+ // No need to include LocalDatabase instances
+ // ( i.e. databases with client connections )
+ // in return array
+ Database theDatabase =
+ ( Database )sDatabases.
+ get( theNames[ theNamesIndex ] );
+ if ( theDatabase == null )
+ {
+ try
+ {
+ theDatabase =
+ Database.createDatabase(
+ theNames [ theNamesIndex ] ) ;
+ theDBList.add( theDatabase );
+ }
+ catch( Exception theException)
+ {}
+ }
+ }
+ }
+ }
+ }
+ theDatabases = theDBList.toArray();
+ }
+ return theDatabases;
+ }
+
+ public String[] getDatabaseNames( final String inDBFileName )
+ {
+ String[] theDatabaseNames = null;
+ try
+ {
+ final HashSet theDBNames = getDBList( inDBFileName );
+ if ( theDBNames != null && theDBNames.size() > 0 )
+ {
+ theDatabaseNames =
+ ( String[] )theDBNames.toArray( new String[ 0 ] );
+ }
+ }
+ catch( Exception theException )
+ {}
+ return theDatabaseNames;
+ }
+
+ public Object[] openLocalDatabases()
+ {
+ Object[] theLocalDatabases = null;
+ if ( ! sDatabases.isEmpty() )
+ {
+ theLocalDatabases = sDatabases.values().toArray();
+ }
+ return theLocalDatabases;
+ }
+
+ public LocalDatabase openLocalDatabase( final Name inName )
+ throws APOCException
+ {
+ final String theKey = createDatabaseKey( inName );
+ LocalDatabase theLocalDatabase = null;
+ synchronized( sDatabases )
+ {
+ theLocalDatabase = ( LocalDatabase )sDatabases.get( theKey );
+ if ( theLocalDatabase == null )
+ {
+ theLocalDatabase = createNewLocalDatabase( inName );
+ }
+ if ( theLocalDatabase != null )
+ {
+ theLocalDatabase.acquire();
+ }
+ }
+ return theLocalDatabase;
+ }
+
+ public void closeLocalDatabase( final LocalDatabase inLocalDatabase )
+ {
+ synchronized( sDatabases )
+ {
+ if ( inLocalDatabase.release() == 0 )
+ {
+ sDatabases.remove(
+ createDatabaseKey(
+ inLocalDatabase.getName() ) );
+ }
+ }
+ }
+
+ private void addDbToDbList( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase =
+ new Database(sDbListDbName, getLocalDatabaseFileName(inName)) ;
+ HashSet theDBList = theDatabase.getDBList();
+ if ( theDBList == null )
+ {
+ theDBList = new HashSet( 1 );
+ }
+ theDBList.add( createDatabaseKey(inName) );
+ theDatabase.beginTransaction();
+ theDatabase.putDBList( theDBList );
+ theDatabase.endTransaction();
+ theDatabase.close( 0 );
+ }
+
+ private static String createDatabaseKey( final Name inName )
+ {
+ return Database.getDatabaseName(inName);
+ }
+
+ private void createDBHome()
+ throws APOCException
+ {
+ final File theFile = new File( sLDBHome );
+ if ( ! theFile.exists() )
+ {
+ if ( ! theFile.mkdirs() )
+ {
+ throw new APOCException( APOCSymbols.sSymDBEnvCreateFailed );
+ }
+ }
+ else
+ {
+ if ( ! theFile.isDirectory() )
+ {
+ throw new APOCException( APOCSymbols.sSymDBEnvCreateFailed );
+ }
+ }
+ FileAccess.chmod( sLDBHome, 0700 );
+ FileAccess.chmod( theFile.getParent(), 0755 );
+ }
+
+ private LocalDatabase createNewLocalDatabase( final Name inName )
+ throws APOCException
+ {
+ return createNewLocalDatabase( inName, true );
+ }
+
+ private LocalDatabase createNewLocalDatabase( final Name inName,
+ boolean inDeleteRetry )
+ throws APOCException
+ {
+ ensureNonZeroLengthDBFile( inName );
+ try
+ {
+ final LocalDatabase theLocalDatabase = new LocalDatabase( inName );
+ addDbToDbList( inName );
+ sDatabases.put( createDatabaseKey( inName ), theLocalDatabase );
+ return theLocalDatabase;
+ }
+ catch ( Exception theException )
+ {
+ if ( inDeleteRetry )
+ {
+ new File( getLocalDatabaseFilePath(inName)).delete();
+ return createNewLocalDatabase( inName, false );
+ }
+ else
+ {
+ throw new APOCException( theException );
+ }
+ }
+ }
+
+ private void ensureNonZeroLengthDBFile( final Name inName )
+ throws APOCException
+ {
+ File theFile = new File( getLocalDatabaseTmpFilePath( inName ) );
+ try
+ {
+ if ( theFile.exists() )
+ {
+ theFile.delete();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+
+ theFile = new File ( getLocalDatabaseFilePath( inName ) );
+ try
+ {
+ if ( theFile.exists() && theFile.length() == 0 )
+ {
+ theFile.delete();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ /*
+ * 6417522 - default bdb values ( 1000 )for max lockers etc. too small
+ * Adjusting the max. number of lockers dynamically ( based
+ * roughly on MaxClientConnections ) would require the ability
+ * to close & reopen the db environment and all database
+ * dynamically. That's not terribly easy ... at least for our
+ * current implementation.
+ *
+ * As an alternative and considering that additional locks etc.
+ * are really quite cheap ( in terms of memory usge ), have
+ * decided that a practical solution to running out of locks etc.
+ * is to set the max at a ( most likely ) unreachable value.
+ * The number of locks required per user connection seems to
+ * vary dependent on the platform but 12 is a reasonable
+ * generalisation.
+ * For the moment, I'm using a default value of 12000 for max.
+ * locks. This would allow approx. 1000 users to connect. It
+ * also has no significant impact on memory use.
+ */
+ private void initLocks()
+ throws DbException
+ {
+ int theCount = DaemonConfig.getIntProperty( DaemonConfig.sMaxDbLocks );
+ setLockMaxLockers( theCount );
+ setLockMaxLocks( theCount );
+ setLockMaxObjects( theCount );
+ }
+
+ private void openEnv()
+ throws APOCException
+ {
+ try
+ {
+ new DbEnv( 0 ).remove( sLDBHome, Db.DB_FORCE );
+ open( sLDBHome, sDbEnvFlags, sDbEnvMode );
+ }
+ catch( DbException theException )
+ {
+ APOCLogger.throwing( "LocalDatabaseFactory",
+ "openEnv",
+ theException );
+ throw new APOCException( theException );
+ }
+ catch( FileNotFoundException theException )
+ {
+ APOCLogger.throwing( "LocalDatabaseFactory",
+ "openEnv",
+ theException );
+ throw new APOCException( theException );
+ }
+ }
+
+ private HashSet getDBList( final String inDBFileName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase = new Database(sDbListDbName,
+ inDBFileName) ;
+ final HashSet theList = theDatabase.getDBList();
+ theDatabase.close( 0 );
+ return theList;
+ }
+
+ public static String getLocalDatabaseFileName( final Name inName )
+ {
+ return new StringBuffer(inName.getEntityType())
+ .append(".")
+ .append(inName.getEntityName()).toString();
+ }
+
+ private static String getLocalDatabaseFilePath( final Name inName )
+ {
+ return new StringBuffer( sLDBHome )
+ .append( File.separatorChar )
+ .append(getLocalDatabaseFileName(inName) )
+ .toString();
+ }
+
+ private static String getLocalDatabaseTmpFilePath( final Name inName )
+ {
+ return new StringBuffer( sLDBHome )
+ .append( File.separatorChar )
+ .append( s__dbPrefix )
+ .append( getLocalDatabaseFileName( inName ) )
+ .toString();
+ }
+
+ private HashSet removeDbFromDbList( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase =
+ new Database( sDbListDbName, getLocalDatabaseFileName( inName ) );
+ /*
+ * 6417504 - ensure Db handle is closed to avoid leak
+ */
+ HashSet theDBList = null;
+ try
+ {
+ theDBList = theDatabase.getDBList();
+ if ( theDBList != null )
+ {
+ theDBList.remove( inName.toString() );
+ theDatabase.beginTransaction();
+ theDatabase.putDBList( theDBList );
+ theDatabase.endTransaction();
+ }
+ }
+ finally
+ {
+ theDatabase.close( 0 );
+ }
+ return theDBList;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/SetDbt.java b/src/com/sun/apoc/daemon/localdatabase/SetDbt.java
new file mode 100644
index 0000000..e06fe6c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/SetDbt.java
@@ -0,0 +1,96 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import java.nio.*;
+import java.util.*;
+
+class SetDbt extends Dbt
+{
+ SetDbt()
+ {
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ SetDbt( final HashSet inValue )
+ {
+ setApocData( inValue );
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ void setApocData( final HashSet inValue )
+ {
+ int theSize = 0;
+ Iterator theIterator = inValue.iterator();
+ while ( theIterator.hasNext() )
+ {
+ theSize += ( ( String )theIterator.next() ).length() + 1;
+ }
+ ByteBuffer theBuffer = ByteBuffer.allocate( theSize );
+ theIterator = inValue.iterator();
+ while ( theIterator.hasNext() )
+ {
+ theBuffer
+ .put( ( ( String )theIterator.next() ).getBytes() )
+ .put( ( byte )0 );
+ }
+ theBuffer.flip();
+ set_data( theBuffer.array() );
+ set_size( theSize );
+ }
+
+ HashSet getApocData()
+ {
+ byte[] theByte = { 0 };
+ String theString = new String( theByte );
+ HashSet theData = null;
+ int theSize = get_size();
+ if ( theSize > 0 )
+ {
+ final StringTokenizer theTokenizer =
+ new StringTokenizer(
+ new String( get_data(), get_offset(), theSize ),
+ theString );
+ theData = new HashSet();
+ while ( theTokenizer.hasMoreTokens() )
+ {
+ theData.add( theTokenizer.nextToken() );
+ }
+ }
+ return theData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/StringDbt.java b/src/com/sun/apoc/daemon/localdatabase/StringDbt.java
new file mode 100644
index 0000000..afd46da
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/StringDbt.java
@@ -0,0 +1,70 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+class StringDbt extends Dbt
+{
+ StringDbt()
+ {
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ StringDbt( final String inValue )
+ {
+ setApocData( inValue );
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ void setApocData( final String inValue )
+ {
+ final byte[] theData = inValue.getBytes();
+ set_data( theData );
+ set_size( theData.length );
+ }
+
+ String getApocData()
+ {
+ String theData = null;
+ int theSize = get_size();
+
+ if ( theSize > 0 )
+ {
+ theData = new String( get_data(), get_offset(), theSize );
+ }
+ return theData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/Timestamp.java b/src/com/sun/apoc/daemon/localdatabase/Timestamp.java
new file mode 100644
index 0000000..7faff34
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/Timestamp.java
@@ -0,0 +1,108 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import java.util.*;
+
+public class Timestamp
+{
+ private static final TimeZone sUTC = TimeZone.getTimeZone( "UTC" );
+
+ public static final String sEpoch = "19700101000000Z";
+ public static final long sEpochMillis = 0;
+
+ public static String getTimestamp()
+ {
+ StringBuffer theBuffer = new StringBuffer( 15 );
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theBuffer.append( theCalendar.get( Calendar.YEAR ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MONTH ) + 1 );
+ padAppend( theBuffer, theCalendar.get( Calendar.DAY_OF_MONTH ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.HOUR_OF_DAY ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MINUTE ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.SECOND ) );
+ theBuffer.append( "Z" );
+ return theBuffer.toString();
+ }
+
+ public static String getTimestamp( long inMillis )
+ {
+ StringBuffer theBuffer = new StringBuffer( 15 );
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theCalendar.setTimeInMillis( inMillis );
+ theBuffer.append( theCalendar.get( Calendar.YEAR ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MONTH ) + 1 );
+ padAppend( theBuffer, theCalendar.get( Calendar.DAY_OF_MONTH ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.HOUR_OF_DAY ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MINUTE ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.SECOND ) );
+ theBuffer.append( "Z" );
+ return theBuffer.toString();
+ }
+
+ public static long getMillis( String inTimestamp )
+ {
+ if ( inTimestamp == null || inTimestamp.compareTo( sEpoch ) == 0 )
+ {
+ return sEpochMillis;
+ }
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theCalendar.set(
+ Integer.parseInt( inTimestamp.substring( 0, 4 ) ),
+ Integer.parseInt( inTimestamp.substring( 4, 6 ) ) - 1,
+ Integer.parseInt( inTimestamp.substring( 6, 8 ) ),
+ Integer.parseInt( inTimestamp.substring( 8, 10 ) ),
+ Integer.parseInt( inTimestamp.substring( 10, 12 ) ),
+ Integer.parseInt( inTimestamp.substring( 12, 14 ) ) );
+ return theCalendar.getTimeInMillis();
+ }
+
+ public static boolean isNewer( String inTimestamp1, String inTimestamp2 )
+ {
+ String theTimestamp1 = inTimestamp1.substring( 0, 14 );
+ String theTimestamp2 = inTimestamp2.substring( 0, 14 );
+ return Long.parseLong( theTimestamp1 ) >
+ Long.parseLong( theTimestamp2 );
+ }
+
+ private static void padAppend( StringBuffer inBuffer, int inValue )
+ {
+ if ( inValue < 10 )
+ {
+ inBuffer.append( 0 );
+ }
+ inBuffer.append( inValue );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java b/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java
new file mode 100755
index 0000000..f3045fd
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java
@@ -0,0 +1,75 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sun.apoc.spi.policies.*;
+
+import java.util.*;
+
+public class UpdateItem
+{
+ public static final int NOCHANGE = 0;
+ public static final int ADD = 1;
+ public static final int REMOVE = 2;
+ public static final int MODIFY = 3;
+
+ private int mUpdateType;
+ private final String mComponentName;
+ private final Policy[] mPolicies;
+
+ public UpdateItem()
+ {
+ mComponentName = null;
+ mPolicies = null;
+ }
+
+ public UpdateItem( int inUpdateType,
+ final String inComponentName,
+ final Policy[] inPolicies )
+ {
+ mUpdateType = inUpdateType;
+ mComponentName = inComponentName;
+ mPolicies = inPolicies;
+ }
+
+ public int getUpdateType() { return mUpdateType; }
+ public final String getComponentName() { return mComponentName; }
+ public final Policy[] getPolicies() { return mPolicies; }
+
+ public void setUpdateType( int inUpdateType )
+ {
+ mUpdateType = inUpdateType;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java b/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java
new file mode 100644
index 0000000..5ea9394
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import java.util.*;
+
+class VectorStringDbt extends Dbt
+{
+ VectorStringDbt()
+ {
+ super() ;
+ set_flags(Db.DB_DBT_MALLOC) ;
+ }
+
+ VectorStringDbt(final Vector inValue)
+ {
+ super() ;
+ fillData(inValue) ;
+ set_flags(Db.DB_DBT_MALLOC) ;
+ }
+
+ private void fillData(final Vector inValue)
+ {
+ Iterator theIterator = inValue.iterator() ;
+ int theTotalLength = 0 ;
+
+ while (theIterator.hasNext())
+ {
+ theTotalLength += ((String) theIterator.next()).length() ;
+ ++ theTotalLength ; // The intermediate 0
+ }
+ byte [] theData = new byte [theTotalLength] ;
+ int theCurrentIndex = 0 ;
+
+ theIterator = inValue.iterator() ;
+ while (theIterator.hasNext())
+ {
+ byte [] theSource = ((String) theIterator.next()).getBytes() ;
+
+ for (int i = 0 ; i < theSource.length ; ++ i)
+ {
+ theData [theCurrentIndex ++] = theSource [i] ;
+ }
+ theData [theCurrentIndex ++] = 0 ;
+ }
+ set_data(theData) ;
+ set_size(theTotalLength) ;
+ }
+
+ Vector retrieveData()
+ {
+ Vector theData = null ;
+ int theSize = get_size() ;
+
+ if (theSize > 0)
+ {
+ int theStart = 0 ;
+ int theEnd = 0 ;
+ byte [] theArray = get_data() ;
+
+ theData = new Vector() ;
+ do
+ {
+ while (theEnd < theSize && theArray [theEnd] != 0)
+ {
+ ++ theEnd ;
+ }
+ theData.add(new String(theArray, theStart, theEnd - theStart)) ;
+ ++ theEnd ;
+ theStart = theEnd ;
+ } while (theEnd < theSize) ;
+ }
+ return theData ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java b/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java
new file mode 100644
index 0000000..bfc203e
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java
@@ -0,0 +1,133 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class AddListenerMessage extends Message
+{
+ private Vector mComponentNames;
+ private String mClientData;
+ private int[] mExpectedSymbols = { APOCSymbols.sSymParamSessionId,
+ APOCSymbols.sSymUnknown };
+ private boolean mIsValid = false;
+
+ public AddListenerMessage()
+ {
+ super( APOCSymbols.sSymReqAddListener );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public String getClientData() { return mClientData; }
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamClientData:
+ addClientData( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbols( APOCSymbols.sSymParamClientData,
+ APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addClientData( final String inClientData )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamClientData );
+ mClientData = inClientData;
+ setCheckSymbols( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbols[ 0 ] == APOCSymbols.sSymUnknown ||
+ ( mExpectedSymbols[ 0 ] != inSymbol &&
+ mExpectedSymbols[ 1 ] != inSymbol ) )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbols( final int inSymbol )
+ {
+ setCheckSymbols( inSymbol, APOCSymbols.sSymUnknown );
+ }
+
+ private void setCheckSymbols( final int inSymbol1, final int inSymbol2 )
+ {
+ mExpectedSymbols[ 0 ] = inSymbol1;
+ mExpectedSymbols[ 1 ] = inSymbol2;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java b/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java
new file mode 100644
index 0000000..571c337
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java
@@ -0,0 +1,111 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.messaging ;
+
+import java.util.Hashtable ;
+
+import com.sun.apoc.daemon.apocd.Client ;
+
+import com.sun.apoc.daemon.misc.APOCException ;
+import com.sun.apoc.daemon.misc.APOCSymbols ;
+
+public class CreateSessionExtMessage extends Message
+ implements CredentialsProviderMessage {
+ private String mUserId = null ;
+ private String mCredentials = null ;
+ private Hashtable mEntities = new Hashtable() ;
+ private int mExpectedSymbol = APOCSymbols.sSymParamUserId ;
+ private String mLastEntityType = null ;
+ private boolean mIsValid = false ;
+
+ public CreateSessionExtMessage() {
+ super(APOCSymbols.sSymReqCreateSessionExt) ;
+ }
+ public boolean isValid() { return mIsValid ; }
+ public String getUserId() { return mUserId ; }
+ public String getCredentials() { return mCredentials ; }
+ public Hashtable getEntities() { return mEntities ; }
+
+ protected void addParameter(final String aName,
+ final String aValue) throws APOCException {
+ switch (APOCSymbols.getProtocolSymbol(aName)) {
+ case APOCSymbols.sSymParamUserId:
+ setUserId(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamCredentials:
+ setCredentials(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamEntityType:
+ setEntityType(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamEntityId:
+ setEntityId(aValue) ;
+ }
+ }
+ private void setUserId(final String aUserId) throws APOCException {
+ checkState(APOCSymbols.sSymParamUserId) ;
+ mUserId = aUserId ;
+ mExpectedSymbol = APOCSymbols.sSymParamCredentials ;
+ }
+ private void setCredentials(
+ final String aCredentials) throws APOCException {
+ checkState(APOCSymbols.sSymParamCredentials) ;
+ mCredentials = aCredentials ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityType ;
+ }
+ private void setEntityType(final String aEntityType) throws APOCException {
+ try { checkState(APOCSymbols.sSymParamEntityType) ; }
+ catch (APOCException exception) {
+ // Allow for skipping credentials
+ if (mExpectedSymbol != APOCSymbols.sSymParamCredentials) {
+ throw exception ;
+ }
+ }
+ if (mEntities.contains(aEntityType)) { throw new APOCException() ; }
+ mLastEntityType = aEntityType ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityId ;
+ }
+ private void setEntityId(final String aEntityId) throws APOCException {
+ checkState(APOCSymbols.sSymParamEntityId) ;
+ mEntities.put(mLastEntityType, aEntityId) ;
+ mIsValid = true ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityType ;
+ }
+ private void checkState(final int aSymbol) throws APOCException {
+ if (aSymbol != mExpectedSymbol) { throw new APOCException() ; }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java b/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java
new file mode 100644
index 0000000..3b85514
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java
@@ -0,0 +1,134 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class CreateSessionMessage extends Message
+ implements CredentialsProviderMessage
+{
+ private String mUserId;
+ private String mEntityId;
+ private String mCredentials;
+ private int[] mExpectedSymbols= { APOCSymbols.sSymParamUserId,
+ APOCSymbols.sSymUnknown };
+ private boolean mIsValid = false;
+
+ public CreateSessionMessage()
+ {
+ super( APOCSymbols.sSymReqCreateSession );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public String getUserId() { return mUserId; }
+ public String getEntityId() { return mEntityId; }
+ public String getCredentials() { return mCredentials; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamUserId:
+ addUserId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamEntityId:
+ addEntityId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamCredentials:
+ addCredentials( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addUserId( final String inUserId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamUserId );
+ mUserId = inUserId;
+ setCheckSymbols( APOCSymbols.sSymParamEntityId,
+ APOCSymbols.sSymParamCredentials );
+ mIsValid = true;
+ }
+
+ private void addEntityId( final String inEntityId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamEntityId );
+ mEntityId = inEntityId;
+ setCheckSymbols( APOCSymbols.sSymParamCredentials );
+ }
+
+ private void addCredentials( final String inCredentials )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamCredentials );
+ mCredentials = inCredentials;
+ setCheckSymbols( APOCSymbols.sSymUnknown );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbols[ 0 ] == APOCSymbols.sSymUnknown ||
+ ( mExpectedSymbols[ 0 ] != inSymbol &&
+ mExpectedSymbols[ 1 ] != inSymbol ) )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbols( final int inSymbol )
+ {
+ setCheckSymbols( inSymbol,
+ APOCSymbols.sSymUnknown );
+ }
+
+ private void setCheckSymbols( final int inSymbol1,
+ final int inSymbol2 )
+ {
+ mExpectedSymbols[ 0 ] = inSymbol1;
+ mExpectedSymbols[ 1 ] = inSymbol2;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java b/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java
new file mode 100644
index 0000000..1815090
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.messaging ;
+
+public interface CredentialsProviderMessage {
+ public String getCredentials() ;
+}
+
diff --git a/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java b/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java
new file mode 100644
index 0000000..f136497
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class DestroySessionMessage extends Message
+{
+ private boolean mIsValid = false;
+
+ public DestroySessionMessage()
+ {
+ super( APOCSymbols.sSymReqDestroySession );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ if ( APOCSymbols.getProtocolSymbol( inName ) !=
+ APOCSymbols.sSymParamSessionId ||
+ mSessionId != null )
+ {
+ throw new APOCException();
+ }
+ mSessionId = inValue;
+ mIsValid = true;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ListMessage.java b/src/com/sun/apoc/daemon/messaging/ListMessage.java
new file mode 100644
index 0000000..78e65c8
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ListMessage.java
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class ListMessage extends Message
+{
+ private boolean mIsValid = false;
+
+ public ListMessage()
+ {
+ super( APOCSymbols.sSymReqList );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ if ( APOCSymbols.getProtocolSymbol( inName ) !=
+ APOCSymbols.sSymParamSessionId ||
+ mSessionId != null )
+ {
+ throw new APOCException();
+ }
+ mSessionId = inValue;
+ mIsValid = true;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Message.java b/src/com/sun/apoc/daemon/messaging/Message.java
new file mode 100644
index 0000000..90f1a9e
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Message.java
@@ -0,0 +1,80 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.nio.ByteBuffer;
+
+public abstract class Message
+{
+ protected int mName;
+ protected String mSessionId;
+
+ public int getName() { return mName; }
+ public String getSessionId() { return mSessionId; }
+
+ protected Message( final int inName )
+ {
+ mName = inName;
+ }
+
+ protected abstract void addParameter( String inName, String inValue )
+ throws APOCException;
+
+ public abstract boolean isValid();
+
+ private static final byte [] sBindingHeader =
+ APOCSymbols.sContentLength.getBytes() ;
+ private static final int sBindingHeaderLen = sBindingHeader.length ;
+
+ public ByteBuffer serialise()
+ {
+ final byte [] theContent = toString().getBytes() ;
+ final byte [] theContentLength =
+ String.valueOf(theContent.length).getBytes() ;
+
+ return (ByteBuffer) ByteBuffer.allocate(sBindingHeaderLen +
+ theContentLength.length +
+ 2 + // "\r\n"
+ theContent.length)
+ .put(sBindingHeader)
+ .put(theContentLength)
+ .put((byte) '\r')
+ .put((byte) '\n')
+ .put(theContent)
+ .flip() ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/MessageFactory.java b/src/com/sun/apoc/daemon/messaging/MessageFactory.java
new file mode 100644
index 0000000..1f99e91
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/MessageFactory.java
@@ -0,0 +1,113 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class MessageFactory
+{
+ public static Message createRequest( final String inMessageName )
+ throws APOCException
+ {
+ Message theMessage;
+ switch ( APOCSymbols.getProtocolSymbol( inMessageName ) )
+ {
+ case APOCSymbols.sSymReqRead:
+ theMessage = new ReadMessage();
+ break;
+
+ case APOCSymbols.sSymReqList:
+ theMessage = new ListMessage();
+ break;
+
+ case APOCSymbols.sSymReqAddListener:
+ theMessage = new AddListenerMessage();
+ break;
+
+ case APOCSymbols.sSymReqCreateSession:
+ theMessage = new CreateSessionMessage();
+ break;
+
+ case APOCSymbols.sSymReqCreateSessionExt:
+ theMessage = new CreateSessionExtMessage();
+ break;
+
+ case APOCSymbols.sSymReqDestroySession:
+ theMessage = new DestroySessionMessage();
+ break;
+
+ case APOCSymbols.sSymReqRemoveListener:
+ theMessage = new RemoveListenerMessage();
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ return theMessage;
+ }
+
+ public static Message createResponse( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ Message theMessage = null;
+ switch ( inResponseType )
+ {
+ case APOCSymbols.sSymRespSuccess:
+ case APOCSymbols.sSymRespInvalidRequest:
+ case APOCSymbols.sSymRespConnectionFailure:
+ case APOCSymbols.sSymRespAuthenticationFailure:
+ case APOCSymbols.sSymRespInvalidSessionId:
+ case APOCSymbols.sSymRespNoSuchComponent:
+ case APOCSymbols.sSymRespUnknownFailure:
+ case APOCSymbols.sSymRespSuccessContinueLocalAuth:
+ case APOCSymbols.sSymRespSuccessContinueSASLAuth:
+ theMessage = new Response( inResponseType,
+ inSessionId,
+ inResponseMessage );
+ break;
+
+ default:
+ break;
+ }
+ return theMessage;
+ }
+
+ public static Message createNotification( final String inSessionId,
+ int inType )
+ {
+ return new Notification( inSessionId, inType );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Messenger.java b/src/com/sun/apoc/daemon/messaging/Messenger.java
new file mode 100644
index 0000000..874f0bf
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Messenger.java
@@ -0,0 +1,91 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+
+public class Messenger
+{
+ private ClientChannel mClientChannel;
+ private RequestReceiver mRequestReceiver = new RequestReceiver();
+
+ public Messenger()
+ throws APOCException
+ {
+ }
+
+ public void setClientChannel( final ClientChannel inClientChannel )
+ {
+ mClientChannel = inClientChannel;
+ }
+
+ public Message receiveRequest()
+ throws APOCException
+ {
+ return receiveRequest( true );
+ }
+
+ public Message receiveRequest( boolean inSetBusy )
+ throws APOCException
+ {
+ return mRequestReceiver.receiveRequest( mClientChannel );
+ }
+
+ public void sendResponse( final Message inResponse )
+ {
+ sendResponse( inResponse, true );
+ }
+
+ public void sendResponse( final Message inResponse, boolean inSetIdle )
+ {
+ try
+ {
+ if ( inSetIdle )
+ {
+ mClientChannel.registerForSelection( true );
+ }
+ mClientChannel.write( inResponse.serialise() );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.finest( "Msgr001" );
+ APOCLogger.throwing( "Messenger", "sendResponse", theException );
+ }
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Notification.java b/src/com/sun/apoc/daemon/messaging/Notification.java
new file mode 100644
index 0000000..3518041
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Notification.java
@@ -0,0 +1,119 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class Notification extends Message
+{
+ private String mComponentName;
+ private String mClientData;
+
+ public Notification( final String inSessionId,
+ int inType )
+ {
+ super( inType );
+ mSessionId = inSessionId;
+ }
+
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ public void setComponentName( final String inComponentName )
+ {
+ mComponentName = inComponentName;
+ }
+
+ public void setClientData( final String inClientData )
+ {
+ mClientData = inClientData;
+ }
+
+ public String toString()
+ {
+ StringBuffer theBuffer =
+ new StringBuffer()
+ .append( "<" )
+ .append( APOCSymbols.getProtocolString( mName ) )
+ .append( ">" )
+
+ .append( "<" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">" )
+
+ .append( mSessionId )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">");
+
+ if ( mClientData != null )
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamClientData )
+ .append( ">" )
+
+ .append( mClientData )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamClientData )
+ .append( ">" );
+ }
+
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+
+ .append( mComponentName )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+
+ .append( "</" )
+ .append( APOCSymbols.getProtocolString( mName ) )
+ .append( ">" );
+ return theBuffer.toString();
+ }
+
+ protected void addParameter( String inName, String inValue )
+ throws APOCException
+ {
+ throw new APOCException();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java b/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java
new file mode 100644
index 0000000..607e1ef
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java
@@ -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import javax.xml.parsers.*;
+
+class ProtocolDeserialiser
+{
+ private InputStream mInputStream;
+ private final XMLReader mXMLReader;
+ private final ProtocolHandler mHandler =
+ new ProtocolHandler();
+ private static final SAXParserFactory sSAXParserFactory =
+ SAXParserFactory.newInstance();
+
+ public ProtocolDeserialiser()
+ throws SAXException, ParserConfigurationException
+ {
+ mXMLReader = sSAXParserFactory.newSAXParser().getXMLReader();
+ mXMLReader.setContentHandler( mHandler );
+ }
+
+ public void setInputStream( final InputStream inInputStream )
+ {
+ mInputStream = inInputStream;
+ }
+
+ public Message deserialise()
+ throws IOException, SAXException
+ {
+ mXMLReader.parse( new InputSource( mInputStream ) );
+ return mHandler.getMessage();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java b/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java
new file mode 100644
index 0000000..20d77e2
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java
@@ -0,0 +1,103 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+class ProtocolHandler extends DefaultHandler
+{
+ private Message mMessage;
+ private String mCurrentParamName;
+
+ public Message getMessage()
+ {
+ return mMessage;
+ }
+
+ public void characters( final char[] inCharArray, final int inStart, final int inLength )
+ throws SAXException
+ {
+ if ( mMessage == null )
+ {
+ throw new SAXException( new APOCException() );
+ }
+
+ try
+ {
+ mMessage.addParameter( mCurrentParamName,
+ new String( inCharArray, inStart, inLength ) );
+ }
+ catch ( APOCException theException )
+ {
+ throw new SAXException( theException );
+ }
+ }
+
+ public void startDocument()
+ {
+ init();
+ }
+
+ public void startElement( final String inURI,
+ final String inName,
+ final String inQName,
+ final Attributes inAttributes )
+ throws SAXException
+ {
+ if ( mMessage == null )
+ {
+ try
+ {
+ mMessage = MessageFactory.createRequest( inQName );
+ }
+ catch( APOCException theException )
+ {
+ throw new SAXException( theException );
+ }
+ }
+ else
+ {
+ mCurrentParamName = inQName;
+ }
+ }
+
+ private void init()
+ {
+ mMessage = null;
+ mCurrentParamName = null;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java b/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java
new file mode 100644
index 0000000..36eb9f6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java
@@ -0,0 +1,206 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.nio.*;
+
+class ProtocolUnbinder extends InputStream implements ConfigEventListener
+{
+ private ClientChannel mClientChannel;
+ private final ByteBuffer mInputBuffer = ByteBuffer.allocate( 1024 );
+ private int mContentLength;
+ private final StringBuffer mContentLengthBuffer =
+ new StringBuffer( sContentLengthValueSize );
+ private long mAvailableByteCount;
+
+ private static int sMaxRequestLengthMinimum= 4096;
+ private static Integer sMaxRequestLength =
+ new Integer( sMaxRequestLengthMinimum );
+ private static final byte[] sContentLengthHeader =
+ APOCSymbols.sContentLength.getBytes();
+ private static final int sContentLengthValueSize = 5;
+
+ static
+ {
+ setMaxRequestLength();
+ }
+
+ public ProtocolUnbinder()
+ {
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public void setClientChannel( final ClientChannel inClientChannel )
+ {
+ mClientChannel = inClientChannel;
+ mAvailableByteCount = 0;
+ }
+
+ public void onConfigEvent()
+ {
+ setMaxRequestLength();
+ }
+
+ public int read()
+ throws IOException
+ {
+ int theByte = -1;
+ if ( mContentLength-- > 0 )
+ {
+ theByte = ( int )getByte();
+ }
+ return theByte;
+ }
+
+ public int read( final byte[] outBytes, final int inOffset, final int inByteCount )
+ throws IOException
+ {
+ int theByteCount = 0;
+ while ( mContentLength > 0 && theByteCount < inByteCount )
+ {
+ outBytes[ inOffset + theByteCount++ ] = getByte();
+ mContentLength--;
+ }
+ return theByteCount > 0 ? theByteCount : -1;
+ }
+
+ public InputStream unbind()
+ throws APOCException, IOException
+ {
+ mContentLength = getContentLength();
+ if ( mContentLength == 0 || mContentLength > getMaxRequestLength() )
+ {
+ throw new APOCException( APOCSymbols.sSymRespInvalidRequest );
+ }
+ return this;
+ }
+
+ private byte getByte()
+ throws IOException
+ {
+ if ( mAvailableByteCount == 0 )
+ {
+ mInputBuffer.clear();
+ mAvailableByteCount = mClientChannel.read( mInputBuffer );
+ mInputBuffer.flip();
+ }
+ mAvailableByteCount--;
+ return mInputBuffer.get();
+ }
+
+ private int getContentLength()
+ throws IOException
+ {
+ return hasContentHeader() ? readContentLength() : 0;
+ }
+
+ private int getMaxRequestLength()
+ {
+ synchronized( sMaxRequestLength )
+ {
+ return sMaxRequestLength.intValue();
+ }
+ }
+
+ private boolean hasContentHeader()
+ throws IOException
+ {
+ boolean hasContentHeader = true;
+ for ( int theIndex = 0;
+ theIndex < sContentLengthHeader.length;
+ theIndex ++ )
+ {
+ if ( getByte() != sContentLengthHeader[ theIndex ] )
+ {
+ hasContentHeader = false;
+ break;
+ }
+ }
+ return hasContentHeader;
+ }
+
+ private int readContentLength()
+ throws IOException
+ {
+
+ mContentLengthBuffer.delete( 0, sContentLengthValueSize );
+ byte theByte = 0;
+ for ( int theIndex = 0 ;
+ theIndex < sContentLengthValueSize ;
+ theIndex ++ )
+ {
+ if ( ( theByte = getByte() ) == '\r' )
+ {
+ break;
+ }
+ else
+ {
+ mContentLengthBuffer.append( ( char )theByte );
+ }
+ }
+ if ( theByte != '\r' )
+ {
+ getByte(); // skip '\r'
+ }
+ getByte(); // skip '\n'
+ return Integer.parseInt( mContentLengthBuffer.toString() );
+ }
+
+ private static void setMaxRequestLength()
+ {
+ synchronized( sMaxRequestLength )
+ {
+ int theMaxRequestLength =
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxRequestSize );
+ if ( theMaxRequestLength < sMaxRequestLengthMinimum )
+ {
+ String theRequestSizes[] =
+ {
+ String.valueOf( theMaxRequestLength ),
+ String.valueOf( sMaxRequestLengthMinimum ),
+ String.valueOf( sMaxRequestLengthMinimum )
+ };
+ APOCLogger.warning( "Punb001", theRequestSizes );
+ theMaxRequestLength = sMaxRequestLengthMinimum;
+ }
+ sMaxRequestLength = new Integer( theMaxRequestLength );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ReadMessage.java b/src/com/sun/apoc/daemon/messaging/ReadMessage.java
new file mode 100644
index 0000000..e7399f2
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ReadMessage.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class ReadMessage extends Message
+{
+ private Vector mComponentNames;
+ private int mExpectedSymbol = APOCSymbols.sSymParamSessionId;
+ private boolean mIsValid = false;
+
+ public ReadMessage()
+ {
+ super( APOCSymbols.sSymReqRead );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbol( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbol != inSymbol )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbol( final int inSymbol )
+ {
+ mExpectedSymbol = inSymbol;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java b/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java
new file mode 100644
index 0000000..d50fd0c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class RemoveListenerMessage extends Message
+{
+ private Vector mComponentNames;
+ private int mExpectedSymbol = APOCSymbols.sSymParamSessionId;
+ private boolean mIsValid = false;
+
+ public RemoveListenerMessage()
+ {
+ super( APOCSymbols.sSymReqRemoveListener );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbol( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbol != inSymbol )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbol( final int inSymbol )
+ {
+ mExpectedSymbol = inSymbol;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/RequestReceiver.java b/src/com/sun/apoc/daemon/messaging/RequestReceiver.java
new file mode 100644
index 0000000..0781793
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/RequestReceiver.java
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+
+class RequestReceiver
+{
+ private ProtocolUnbinder mUnbinder;
+ private ProtocolDeserialiser mDeserialiser;
+
+ public RequestReceiver()
+ throws APOCException
+ {
+ try
+ {
+ mUnbinder = new ProtocolUnbinder();
+ mDeserialiser = new ProtocolDeserialiser();
+ }
+ catch ( org.xml.sax.SAXException theException )
+ {
+ throw new APOCException( theException );
+ }
+ catch ( javax.xml.parsers.ParserConfigurationException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public Message receiveRequest( final ClientChannel inClientChannel )
+ throws APOCException
+ {
+ Message theMessage;
+ try
+ {
+ mUnbinder.setClientChannel( inClientChannel );
+ mDeserialiser.setInputStream( mUnbinder.unbind() );
+ theMessage = mDeserialiser.deserialise();
+ if ( ! theMessage.isValid() )
+ {
+ throw new APOCException( APOCSymbols.sSymRespInvalidRequest );
+ }
+ }
+ catch ( org.xml.sax.SAXException theException )
+ {
+ APOCLogger.throwing( "RequestReceiver",
+ "receiveRequest",
+ theException );
+ throw new APOCException( theException );
+ }
+ catch ( IOException theException )
+ {
+ throw new APOCException( theException );
+ }
+ return theMessage;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Response.java b/src/com/sun/apoc/daemon/messaging/Response.java
new file mode 100644
index 0000000..3c8f2de
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Response.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class Response extends Message
+{
+ private String mBody;
+
+ public Response( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ super( inResponseType );
+ setBody( inResponseType, inSessionId, inResponseMessage );
+ }
+
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ throw new APOCException();
+ }
+
+ public String toString()
+ {
+ return mBody;
+ }
+
+ private void setBody( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ final String theResponseType =
+ APOCSymbols.getProtocolString( inResponseType );
+
+ final StringBuffer theBuffer = new StringBuffer()
+ .append( "<" )
+ .append( theResponseType )
+ .append( ">" )
+
+ .append( "<" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">" )
+
+ .append( inSessionId )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">");
+
+ if ( inResponseMessage != null )
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamMessage )
+ .append( ">")
+
+ .append( inResponseMessage )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamMessage )
+ .append( ">");
+ }
+
+ theBuffer.append( "</" )
+ .append( theResponseType )
+ .append( ">" );
+
+ mBody = theBuffer.toString();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java b/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java
new file mode 100644
index 0000000..b275830
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java
@@ -0,0 +1,169 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.io.*;
+import java.util.*;
+
+public class APOCAuthenticator
+{
+ public static final File sAuthDir =
+ new File(
+ new StringBuffer(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( File.separatorChar )
+ .append( ".auth" )
+ .toString() );
+
+ private File mFile;
+ private String mFileName;
+ private byte[] mResponse;
+
+ private static final Random sRandom = new Random();
+ private static int sAuthBufferSize = 20;
+
+ public APOCAuthenticator( final String inUserId )
+ throws APOCException
+ {
+ final String theUserId =
+ inUserId != null ? inUserId : "<Daemon administrator>";
+ APOCLogger.finest( "Auth001", theUserId );
+ try
+ {
+ createAuthFile( inUserId );
+ createAuthToken();
+ }
+ catch( Exception theException )
+ {
+ cleanup();
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException( theException );
+ }
+ }
+
+ public void cleanup()
+ {
+ try
+ {
+ if ( mFile != null )
+ {
+ mFile.delete();
+ mFile = null;
+ }
+ }
+ catch( Exception theException )
+ {}
+ }
+
+ public static int getAuthBufferSize() { return sAuthBufferSize; }
+
+ public byte[] getChallenge()
+ {
+ return mFileName.getBytes();
+ }
+
+ public void processResponse( final byte[] inResponse )
+ throws APOCException
+ {
+ try
+ {
+ if ( inResponse == null || inResponse.length != sAuthBufferSize )
+ {
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException();
+ }
+ for ( int theIndex = 0; theIndex < sAuthBufferSize; theIndex ++ )
+ {
+ if ( mResponse[ theIndex ] != inResponse[ theIndex ] )
+ {
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException();
+ }
+ }
+ APOCLogger.finest( "Auth002" );
+ }
+ finally
+ {
+ cleanup();
+ }
+ }
+
+ private void createAuthFile( final String inUserId )
+ throws Exception
+ {
+ long thePrefix = sRandom.nextLong();
+ thePrefix = thePrefix < 0 ? -thePrefix : thePrefix;
+ mFile =
+ File.createTempFile( String.valueOf( thePrefix ), null, sAuthDir );
+ mFile.deleteOnExit();
+ mFileName = mFile.getAbsolutePath();
+ if ( inUserId != null )
+ {
+ FileAccess.chown( mFileName, inUserId );
+ }
+ FileAccess.chmod( mFileName, 0600 );
+ }
+
+ private void createAuthToken()
+ throws Exception
+ {
+ final FileOutputStream theOutputStream =
+ new FileOutputStream( mFileName );
+ long theValue = sRandom.nextLong();
+ theValue = theValue < 0 ? -theValue : theValue;
+ final StringBuffer theStringBuffer =
+ new StringBuffer().append( theValue );
+ int theLength = theStringBuffer.length();
+ if ( theLength > sAuthBufferSize )
+ {
+ theStringBuffer.delete( sAuthBufferSize + 1, theLength );
+ }
+ else
+ if ( theLength < sAuthBufferSize )
+ {
+ int theExtraCharacters = sAuthBufferSize - theLength;
+ for ( int theIndex = 0; theIndex < theExtraCharacters; theIndex ++ )
+ {
+ theStringBuffer.append( ( int )0 );
+ }
+ }
+ mResponse = theStringBuffer.toString().getBytes();
+ theOutputStream.write( mResponse );
+ theOutputStream.close();
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCException.java b/src/com/sun/apoc/daemon/misc/APOCException.java
new file mode 100644
index 0000000..b84033a
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCException.java
@@ -0,0 +1,98 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.spi.*;
+
+public class APOCException extends Exception
+{
+ private int mCode = APOCSymbols.sSymRespUnknownFailure;
+
+ public APOCException(){}
+
+ public APOCException( final int inCode )
+ {
+ this( inCode, null );
+ }
+
+ public APOCException( final Throwable inThrowable )
+ {
+ this( APOCSymbols.sSymRespUnknownFailure, inThrowable );
+ mCode = getCode( inThrowable );
+ }
+
+ public APOCException( final int inCode, final Throwable inThrowable )
+ {
+ super( inThrowable );
+ mCode = inCode;
+ }
+
+ public int getCode() { return mCode; }
+
+ private int getCode( final Throwable inThrowable )
+ {
+ int theCode = APOCSymbols.sSymRespUnknownFailure;
+ if ( inThrowable != null )
+ {
+ if ( inThrowable instanceof SPIException )
+ {
+ theCode = getCode( ( SPIException )inThrowable );
+ }
+ }
+ return theCode;
+ }
+
+ private int getCode( final SPIException inException )
+ {
+ int theCode = APOCSymbols.sSymRespUnknownFailure;
+ final String theStringCode =
+ inException.getLocalizedErrorMessageCode();
+ if ( theStringCode != null )
+ {
+ if ( theStringCode.compareTo(
+ SPIException.ERROR_OPEN_CONNECTION ) == 0 )
+ {
+ theCode = APOCSymbols.sSymRespConnectionFailure;
+ }
+ else
+ if ( theStringCode.compareTo(
+ SPIException.ERROR_USER_INVALID ) == 0 )
+ {
+ theCode = APOCSymbols.sSymRespAuthenticationFailure;
+ }
+ }
+ return theCode;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCLogger.java b/src/com/sun/apoc/daemon/misc/APOCLogger.java
new file mode 100644
index 0000000..cab6c00
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCLogger.java
@@ -0,0 +1,227 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+
+public class APOCLogger
+{
+ private static final String sLoggerName = "com.sun.apoc.daemon";
+ private static final String sLogDir = "/Logs";
+ private static final String sLogFile = "/apocd.log";
+ private static final Logger sLogger =
+ ConfigurableLogger.getLogger( sLoggerName, sLoggerName );
+ private static final int sLimit = 1000000;
+ private static final int sCount = 5;
+
+ static
+ {
+ try
+ {
+ final Handler theHandler =
+ createHandler(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) );
+ final Level theLevel =
+ Level.parse(
+ DaemonConfig.getStringProperty( DaemonConfig.sLogLevel ) );
+ theHandler.setLevel( theLevel );
+ theHandler.setFormatter( new SimpleFormatter() );
+
+ sLogger.addHandler( theHandler );
+ sLogger.setLevel( theLevel );
+ }
+ catch( Exception theException )
+ {
+ theException.printStackTrace();
+ }
+ }
+
+ public static void config( final String inKey )
+ {
+ sLogger.log( Level.CONFIG, inKey );
+ }
+
+ public static void config( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.CONFIG, inKey, inParam );
+ }
+
+ public static void fine( final String inKey )
+ {
+ sLogger.log( Level.FINE, inKey );
+ }
+
+ public static void fine( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINE, inKey, inParam );
+ }
+
+ public static void finer( final String inKey )
+ {
+ sLogger.log( Level.FINER, inKey );
+ }
+
+ public static void finer( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINER, inKey, inParam );
+ }
+
+ public static void finest( final String inKey )
+ {
+ sLogger.log( Level.FINEST, inKey );
+ }
+
+ public static void finest( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINEST, inKey, inParam );
+ }
+
+ public static boolean isLoggable( final Level inLevel )
+ {
+ return sLogger.isLoggable( inLevel );
+ }
+
+ public static void info( final String inKey )
+ {
+ sLogger.log( Level.INFO, inKey );
+ }
+
+ public static void info( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.INFO, inKey, inParam );
+ }
+
+ public static void severe( final String inKey )
+ {
+ sLogger.log( Level.SEVERE, inKey );
+ }
+
+ public static void severe( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.SEVERE, inKey, inParam );
+ }
+
+ public static void throwing( final String inClass,
+ final String inMethod,
+ final Throwable inThrowable )
+ {
+ sLogger.throwing( inClass, inMethod, inThrowable );
+ }
+
+ public static void warning( final String inKey )
+ {
+ sLogger.log( Level.WARNING, inKey );
+ }
+
+ public static void warning( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.WARNING, inKey, inParam );
+ }
+
+ public static void warning( final String inKey, final Object[] inParams )
+ {
+ sLogger.log( Level.WARNING, inKey, inParams );
+ }
+
+ private static Handler createHandler( final String inDataDir )
+ {
+ Handler theHandler;
+ if ( needFileHandler() && inDataDir != null )
+ {
+ final String theLogDir =
+ new StringBuffer( inDataDir ).append( sLogDir ).toString();
+ createLogDir( theLogDir );
+ try
+ {
+ theHandler =
+ new FileHandler(
+ new StringBuffer( theLogDir )
+ .append( sLogFile )
+ .toString(),
+ sLimit,
+ sCount,
+ true );
+ }
+ catch( Exception theException )
+ {
+ System.err.println("Warning:Failed to create log file handler");
+ theHandler = new ConsoleHandler();
+ }
+ }
+ else
+ {
+ theHandler = new ConsoleHandler();
+ }
+ return theHandler;
+ }
+
+ private static void createLogDir( final String inLogDir )
+ {
+ final File theFile = new File( inLogDir );
+ if ( ! theFile.exists() )
+ {
+ if ( ! theFile.mkdirs() )
+ {
+ System.err.println( "Warning: Cannot create Log directory '" +
+ inLogDir + "'" );
+ }
+ }
+ else
+ {
+ if ( ! theFile.isDirectory() )
+ {
+ System.err.println( "Warning: Log directory '" +
+ inLogDir +
+ "' is actually a file" );
+ }
+ }
+ }
+
+ private static boolean needFileHandler()
+ {
+ boolean needsFileHandler = false;
+ final String theHandler = DaemonConfig.getStringProperty( "handlers" );
+ if ( theHandler == null ||
+ theHandler.compareTo( "java.util.logging.FileHandler" ) == 0 )
+ {
+ needsFileHandler = true;
+ }
+ return needsFileHandler;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCSymbols.java b/src/com/sun/apoc/daemon/misc/APOCSymbols.java
new file mode 100644
index 0000000..8e09528
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCSymbols.java
@@ -0,0 +1,246 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import java.util.*;
+
+public class APOCSymbols
+{
+ public static final int sSymUnknown = 0;
+
+
+ // Protocol Stuff
+ // Binding
+ public static final String sContentLength = "CONTENT-LENGTH:";
+
+ public static final int sSymContentLength = 1;
+
+ // Message Names - Requests
+ public static final String sReqAddListener = "addListener";
+ public static final String sReqCreateSession = "createSession";
+ public static final String sReqDestroySession = "destroySession";
+ public static final String sReqList = "list";
+ public static final String sReqRead = "read";
+ public static final String sReqRemoveListener = "removeListener";
+ public static final String sReqCreateSessionExt = "createSessionExt";
+
+ public static final int sSymReqAddListener = 11;
+ public static final int sSymReqCreateSession = 12;
+ public static final int sSymReqDestroySession = 13;
+ public static final int sSymReqList = 14;
+ public static final int sSymReqRead = 15;
+ public static final int sSymReqRemoveListener = 16;
+ public static final int sSymReqCreateSessionExt = 17;
+
+ // Message Names - Responses
+ public static final String sRespSuccess = "success";
+ public static final String sRespInvalidRequest =
+ "invalidRequest";
+ public static final String sRespConnectionFailure =
+ "connectionFailure";
+ public static final String sRespAuthenticationFailure =
+ "authenticationFailure";
+ public static final String sRespInvalidSessionId =
+ "invalidSessionId";
+ public static final String sRespNoSuchComponent =
+ "noSuchComponent";
+ public static final String sRespUnknownFailure =
+ "unknownFailure";
+ public static final String sRespSuccessContinueLocalAuth =
+ "successContinueLocalAuth";
+ public static final String sRespSuccessContinueSASLAuth =
+ "successContinueSASLAuth";
+
+ public static final int sSymRespSuccess = 20;
+ public static final int sSymRespInvalidRequest = 21;
+ public static final int sSymRespConnectionFailure = 22;
+ public static final int sSymRespAuthenticationFailure = 23;
+ public static final int sSymRespInvalidSessionId = 24;
+ public static final int sSymRespNoSuchComponent = 25;
+ public static final int sSymRespUnknownFailure = 26;
+ public static final int sSymRespSuccessContinueLocalAuth= 27;
+ public static final int sSymRespSuccessContinueSASLAuth = 28;
+
+ // Message Names - Notification
+ public static final String sAddNotification = "addNotification";
+ public static final String sRemoveNotification = "removeNotification";
+ public static final String sModifyNotification = "modifyNotification";
+
+ public static final int sSymAddNotification = 30;
+ public static final int sSymRemoveNotification = 31;
+ public static final int sSymModifyNotification = 32;
+
+ // Message Parameters
+ public static final String sParamUserId = "userId";
+ public static final String sParamEntityId = "entityId";
+ public static final String sParamCredentials = "credentials";
+ public static final String sParamSessionId = "sessionId";
+ public static final String sParamComponentName = "componentName";
+ public static final String sParamClientData = "clientData";
+ public static final String sParamMessage = "message";
+ public static final String sParamVersion = "version";
+ public static final String sParamServer = "server";
+ public static final String sParamAuthType = "authType";
+ public static final String sParamLayer = "layer";
+ public static final String sParamEntityType = "entityType";
+
+ public static final int sSymParamUserId = 40;
+ public static final int sSymParamEntityId = 41;
+ public static final int sSymParamCredentials = 42;
+ public static final int sSymParamSessionId = 43;
+ public static final int sSymParamComponentName = 44;
+ public static final int sSymParamClientData = 45;
+ public static final int sSymParamMessage = 46;
+ public static final int sSymParamVersion = 47;
+ public static final int sSymParamServer = 48;
+ public static final int sSymParamAuthType = 49;
+ public static final int sSymParamLayer = 50;
+ public static final int sSymParamEntityType = 51;
+
+ // Misc
+ public static final String sDBCreateFailed =
+ "Failed to create a db handle";
+ public static final String sDBEnvCreateFailed =
+ "Failed to create a db environment handle";
+ public static final String sCreateServerChannelFailed =
+ "Failed to create a server channel";
+
+ public static final int sSymDBCreateFailed = 60;
+ public static final int sSymDBEnvCreateFailed = 61;
+ public static final int sSymCreateServerChannelFailed = 62;
+
+ private static final Hashtable sProtocolSyms = new Hashtable();
+ private static final Hashtable sProtocolStrs = new Hashtable();
+
+ static
+ {
+ addEntries( sContentLength,
+ new Integer( sSymContentLength ) );
+ addEntries( sReqAddListener,
+ new Integer( sSymReqAddListener ) );
+ addEntries( sReqCreateSession,
+ new Integer( sSymReqCreateSession ) );
+ addEntries( sReqDestroySession,
+ new Integer( sSymReqDestroySession ) );
+ addEntries( sReqList,
+ new Integer( sSymReqList ) );
+ addEntries( sReqRead,
+ new Integer( sSymReqRead ) );
+ addEntries( sReqRemoveListener,
+ new Integer( sSymReqRemoveListener ) );
+ addEntries( sReqCreateSessionExt,
+ new Integer( sSymReqCreateSessionExt ) );
+ addEntries( sRespSuccess,
+ new Integer( sSymRespSuccess ) );
+ addEntries( sRespInvalidRequest,
+ new Integer( sSymRespInvalidRequest ) );
+ addEntries( sRespConnectionFailure,
+ new Integer( sSymRespConnectionFailure ) );
+ addEntries( sRespAuthenticationFailure,
+ new Integer( sSymRespAuthenticationFailure ) );
+ addEntries( sRespInvalidSessionId,
+ new Integer( sSymRespInvalidSessionId ) );
+ addEntries( sRespNoSuchComponent,
+ new Integer( sSymRespNoSuchComponent ) );
+ addEntries( sRespUnknownFailure,
+ new Integer( sSymRespUnknownFailure ) );
+ addEntries( sRespSuccessContinueLocalAuth,
+ new Integer( sSymRespSuccessContinueLocalAuth ) );
+ addEntries( sRespSuccessContinueSASLAuth,
+ new Integer( sSymRespSuccessContinueSASLAuth ) );
+ addEntries( sAddNotification,
+ new Integer( sSymAddNotification ) );
+ addEntries( sRemoveNotification,
+ new Integer( sSymRemoveNotification ) );
+ addEntries( sModifyNotification,
+ new Integer( sSymModifyNotification ) );
+ addEntries( sParamUserId,
+ new Integer( sSymParamUserId ) );
+ addEntries( sParamEntityId,
+ new Integer( sSymParamEntityId ) );
+ addEntries( sParamCredentials,
+ new Integer( sSymParamCredentials ) );
+ addEntries( sParamSessionId,
+ new Integer( sSymParamSessionId ) );
+ addEntries( sParamComponentName,
+ new Integer( sSymParamComponentName ) );
+ addEntries( sParamClientData,
+ new Integer( sSymParamClientData ) );
+ addEntries( sParamMessage,
+ new Integer( sSymParamMessage ) );
+ addEntries( sParamVersion,
+ new Integer( sSymParamVersion ) );
+ addEntries( sParamServer,
+ new Integer( sSymParamServer ) );
+ addEntries( sParamAuthType,
+ new Integer( sSymParamAuthType ) );
+ addEntries( sParamLayer,
+ new Integer( sSymParamLayer ) );
+ addEntries( sParamEntityType,
+ new Integer( sSymParamEntityType ) );
+ addEntries( sDBCreateFailed,
+ new Integer( sSymDBCreateFailed ) );
+ addEntries( sDBEnvCreateFailed,
+ new Integer( sSymDBEnvCreateFailed ) );
+ addEntries( sCreateServerChannelFailed,
+ new Integer( sSymCreateServerChannelFailed ) );
+ }
+
+ private static void addEntries( final String inProtocolString,
+ final Integer inProtocolSymbol )
+ {
+ sProtocolSyms.put( inProtocolString, inProtocolSymbol );
+ sProtocolStrs.put( inProtocolSymbol, inProtocolString );
+ }
+
+ public static int getProtocolSymbol( final String inString )
+ {
+ int theSym = sSymUnknown;
+ if ( inString != null )
+ {
+ final Integer theValue = ( Integer )sProtocolSyms.get( inString );
+ if ( theValue != null )
+ {
+ theSym = theValue.intValue();
+ }
+ }
+ return theSym;
+ }
+
+ public static String getProtocolString( final int inSymbol )
+ {
+ return ( String )sProtocolStrs.get( new Integer( inSymbol ) );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java b/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java
new file mode 100644
index 0000000..8753741
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java
@@ -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.util.logging.*;
+
+public class ConfigurableLogger extends Logger
+ implements ConfigEventListener
+{
+ protected ConfigurableLogger( String inLoggerName,
+ String inResourceBundleName )
+ {
+ super( inLoggerName, inResourceBundleName );
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public static Logger getLogger( String inLoggerName,
+ String inResourceBundleName )
+ {
+ return new ConfigurableLogger( inLoggerName, inResourceBundleName);
+ }
+
+ public void onConfigEvent()
+ {
+ final Level theLevel =
+ Level.parse(
+ DaemonConfig.getStringProperty( DaemonConfig.sLogLevel ) );
+ setLevel( theLevel );
+ final Handler[] theHandlers = getHandlers();
+ if ( theHandlers != null )
+ {
+ for ( int theIndex = 0; theIndex < theHandlers.length; ++ theIndex )
+ {
+ theHandlers[ theIndex ].setLevel( theLevel );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java b/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java
new file mode 100644
index 0000000..312bfa5
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java
@@ -0,0 +1,110 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import java.util.*;
+
+public class DaemonTimerTask
+{
+ private Runnable mRunnable;
+ private long mPeriod = 0;
+ private TimerTask mTimerTask = null;
+ private boolean mIsOneTime = false;
+ private static final Timer sTimer = new Timer( true );
+
+ public DaemonTimerTask( final Runnable inRunnable )
+ {
+ mRunnable = inRunnable;
+ }
+
+ public DaemonTimerTask( final Runnable inRunnable, boolean inIsOneTime )
+ {
+ this( inRunnable );
+ mIsOneTime = inIsOneTime;
+ }
+
+ public void cancel()
+ {
+ setPeriod( -1 );
+ }
+
+ public long getPeriod()
+ {
+ return mPeriod;
+ }
+
+ public boolean setPeriod( long inPeriod )
+ {
+ boolean isChanged = false;
+ if ( inPeriod != mPeriod )
+ {
+ mPeriod = inPeriod;
+ schedule();
+ isChanged = true;
+ }
+ return isChanged;
+ }
+
+ private void schedule()
+ {
+ if ( mPeriod > 0 )
+ {
+ if ( mTimerTask != null )
+ {
+ mTimerTask.cancel();
+ }
+ mTimerTask = new Task();
+ sTimer.schedule( mTimerTask, mPeriod, mPeriod );
+ }
+ else
+ if ( mTimerTask != null )
+ {
+ mTimerTask.cancel();
+ mTimerTask = null;
+ }
+ }
+
+ class Task extends TimerTask
+ {
+ public void run()
+ {
+ mRunnable.run();
+ if ( mIsOneTime )
+ {
+ cancel();
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/FileAccess.java b/src/com/sun/apoc/daemon/misc/FileAccess.java
new file mode 100644
index 0000000..f3b3b02
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/FileAccess.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+public class FileAccess
+{
+ public static native int chmod( final String inFileName, int inMode );
+ public static native int chown( final String inFileName,
+ final String inUserName );
+}
diff --git a/src/com/sun/apoc/daemon/misc/Name.java b/src/com/sun/apoc/daemon/misc/Name.java
new file mode 100644
index 0000000..cc5f9be
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/Name.java
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+public class Name
+{
+ // Location
+ private static int sLocationLocal = 0;
+ private static int sLocationGlobal = 1;
+
+ // Applicability
+ private static int sApplicabilityHost = 2;
+ private static int sApplicabilityUser = 3;
+
+ // Entities
+ private static int sEntityLocalHost = 4;
+ private static int sEntityLocalUser = 5;
+
+ private static int sUndefined = 6;
+
+ private static final String sLocationLocalStr = "local";
+ private static final String sLocationGlobalStr = "global";
+ private static final String sApplicabilityHostStr = "host";
+ private static final String sApplicabilityUserStr = "user";
+ public static final String sEntityLocalHostStr = "localHost";
+ public static final String sEntityLocalUserStr = "localUser";
+
+ public static final String sSep = "/";
+
+ public static final String sNames[] =
+ {
+ sLocationLocalStr,
+ sLocationGlobalStr,
+ sApplicabilityHostStr,
+ sApplicabilityUserStr,
+ sEntityLocalHostStr,
+ sEntityLocalUserStr
+ };
+
+ private String mUserName;
+ private String mEntityType;
+ private String mEntityName;
+ private boolean mIsLocal;
+
+ public Name( final String inUserName,
+ final String inEntityType,
+ final String inEntityName,
+ boolean inIsLocal )
+ {
+ mUserName = inUserName;
+ mEntityType = inEntityType;
+ mEntityName = inEntityName;
+ mIsLocal = inIsLocal;
+ }
+ public Name( final String inUserName,
+ final String inEntityType,
+ final String inEntityName,
+ final String inIsLocal )
+ {
+ mUserName = inUserName ;
+ mEntityType = inEntityType ;
+ mEntityName = inEntityName ;
+ mIsLocal = inIsLocal.compareTo(sLocationLocalStr) == 0 ;
+ }
+
+ public String getUserName() { return mUserName; }
+
+ public String getEntityType() { return mEntityType; }
+
+ public String getEntityName() { return mEntityName; }
+
+ public String getLocation()
+ {
+ return sNames[ getLocationAsInt() ];
+ }
+
+ public int getLocationAsInt()
+ {
+ return mIsLocal ? sLocationLocal : sLocationGlobal;
+ }
+
+ public boolean isLocal() { return mIsLocal; }
+ public boolean isGlobal() { return ! isLocal(); }
+
+ public String toString()
+ {
+ return new StringBuffer(mUserName)
+ .append(sSep)
+ .append(mEntityType)
+ .append(sSep)
+ .append(mEntityName)
+ .append(sSep)
+ .append(getLocation())
+ .toString() ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/properties/apocd.properties b/src/com/sun/apoc/daemon/properties/apocd.properties
new file mode 100644
index 0000000..bdb350f
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/apocd.properties
@@ -0,0 +1,66 @@
+#
+# The port used by the APOC daemon for client requests
+#
+#DaemonPort=3809
+
+#
+# The maximum number of client threads dictates the number of client requests
+# which may be executed simultaneously.
+#
+#MaxClientThreads=5
+
+#
+# The maximum number of client connections allowed
+#
+#MaxClientConnections=50
+
+#
+# The maximum size of requests issued by clients
+#
+#MaxRequestSize=4096
+
+#
+# The interval ( in minutes ) between change detections for daemon config.
+# data
+#
+#DaemonChangeDetectionInterval=10
+
+#
+# The interval ( in minutes ) between change detection for the local database
+#
+#ChangeDetectionInterval=60
+
+#
+# The delay ( in seconds ) between a user session creation and an initial
+# change detection for that user ( if one is due )
+#
+#InitialChangeDetectionDelay=10
+
+#
+# The local database garbage collection interval ( in minutes )
+#
+#GarbageCollectionInterval=10080
+
+#
+# The length of time ( in minutes ) since last read, which non offline
+# components will remain in the local database
+#
+#TimeToLive=10080
+
+#
+# Daemon Log level
+#
+#LogLevel=INFO
+
+#
+# Whether or not local policy should be applied ( if available )
+#ApplyLocalPolicy=true
+
+#
+# The number of seconds after which an uncompleted transaction will be
+# cancelled. A minimum value of 1 second is imposed.
+#TransactionTimeout=15
+
+#
+# The maximum number of Berkeley DB locks available
+#MaxDatabaseLocks=12000
diff --git a/src/com/sun/apoc/daemon/properties/daemon.properties b/src/com/sun/apoc/daemon/properties/daemon.properties
new file mode 100644
index 0000000..2d54129
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/daemon.properties
@@ -0,0 +1,82 @@
+#com.sun.apoc.daemon.admin.AdminManager
+Admr001=Admin manager started
+Admr002=Admin manager stopped
+
+#com.sun.apoc.daemon.apocd.ClientManager
+Clmr001=Client manager started
+Clmr002=Client removed
+Clmr003=Failed to resize thread pool
+Clmr004=Change detection scheduled ( interval = {0} minutes )
+Clmr005=New client added
+Clmr006=Change detection switched off
+Clmr007=Client manager stopped
+
+#com.sun.apoc.daemon.apocd.Daemon
+Dmon001=Daemon starting
+Dmon002=Daemon finishing
+Dmon003=Garbage collection scheduled ( interval = {0} minutes )
+Dmon004=Garbage collection switched off
+
+#com.sun.apoc.daemon.apocd.Session
+Sess001=Creating new client session
+Sess002=New client session created:\n{0}\n
+Sess003=Client session ( sessionId = {0} ) closed
+
+#com.sun.apoc.daemon.config.DaemonConfig
+Dcfg001=Daemon configuration:\n{0}\n
+
+#com.sun.apoc.daemon.messaging.Messenger
+Msgr001=Failed to send response
+
+#com.sun.apoc.daemon.messaging.ProtocolUnbinder
+Punb001=Configured value of MaxRequestSize, {0}, is less than the minimum allowed value ( {1} ). Adjusting MaxRequestsize to {1}.
+
+#com.sun.apoc.daemon.misc.APOCAuthenticator
+Auth001=Authenticating user {0}
+Auth002=Authentication successful
+Auth003=Authentication failed
+
+#com.sun.apoc.daemon.transaction.AddListenerTransaction
+Altn001=AddListener transaction started
+Altn002=AddListener transaction completed
+
+#com.sun.apoc.daemon.transaction.ChangeDetectTransaction
+Cdtn001=ChangeDetect transaction started
+Cdtn002=ChangeDetect transaction completed
+Cdtn003=Notification sent:\n{0}\n
+
+#com.sun.apoc.daemon.transaction.CreateSessionTransaction
+Cstn001=CreateSession transaction started
+Cstn002=CreateSession transaction completed
+
+#com.sun.apoc.daemon.transaction.DestroySessionTransaction
+Dstn001=DestroySession transaction started
+Dstn002=DestroySession transaction completed
+
+#com.sun.apoc.daemon.transaction.GarbageCollectTransaction
+Gctn001=GarbageCollect transaction started
+Gctn002=GarbageCollect transaction completed
+
+#com.sun.apoc.daemon.transaction.ListTransaction
+Lstn001=List transaction started
+Lstn002=List transaction completed
+
+#com.sun.apoc.daemon.transaction.ReadTransaction
+Rdtn001=Read transaction started
+Rdtn002=Read transaction completed
+
+#com.sun.apoc.daemon.transaction.RemoveListenerTransaction
+Rltn001=RemoveListener transaction started
+Rltn002=RemoveListener transaction completed
+
+#com.sun.apoc.daemon.transport.ChannelManager
+Chmr001=Channel manager started
+Chmr002=The maximum number of client connections ( {0} ) has been reached. No new client connections can be established at this time.
+Chmr003=Channel manager stopped
+
+#com.sun.apoc.daemon.transport.ClientChannel
+Clch001=Error while changing channel state ... closing channel
+Clch002=Unexpected EOF while reading client channel
+
+#com.sun.apoc.daemon.transport.ServerChannel
+Svch001=Error while accepting new client channel
diff --git a/src/com/sun/apoc/daemon/properties/defaults.properties b/src/com/sun/apoc/daemon/properties/defaults.properties
new file mode 100644
index 0000000..ae78be6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/defaults.properties
@@ -0,0 +1,83 @@
+#
+# The port used by the APOC daemon for client requests
+#
+DaemonPort=3809
+
+#
+# The maximum number of client threads dictates the number of client requests
+# which may be executed simultaneously.
+#
+MaxClientThreads=5
+
+#
+# The maximum number of client connections allowed
+#
+MaxClientConnections=50
+
+#
+# The maximum size of requests issued by clients
+#
+MaxRequestSize=4096
+
+#
+# The interval ( in minutes ) between change detections for daemon config.
+# data
+#
+DaemonChangeDetectionInterval=10
+
+#
+# The interval ( in minutes ) between change detection for the local database
+#
+ChangeDetectionInterval=60
+
+#
+# The delay ( in seconds ) between a user session creation and an initial
+# change detection for that user ( if one is due )
+#
+InitialChangeDetectionDelay=10
+
+#
+# The local database garbage collection interval ( in minutes )
+#
+GarbageCollectionInterval=10080
+
+#
+# The length of time ( in minutes ) since last read, which non offline
+# components will remain in the local database
+#
+TimeToLive=10080
+
+#
+# The interval ( in minutes ) between detection and removal of idle threads
+#
+IdleThreadDetectionInterval=15
+
+#
+# The length of time ( in minutes ) a thread may remain idle before being
+# removed
+#
+ThreadTimeToLive=5
+
+#
+# The length of time ( in milliseconds ) to wait before timing out a read on
+# client connections
+#
+ConnectionReadTimeout=5000
+
+#
+# Daemon Log level
+#
+LogLevel=INFO
+
+#
+# Whether or not local policy should be applied ( if available )
+ApplyLocalPolicy=true
+
+#
+# The number of seconds after which an uncompleted transaction will be
+# cancelled. A minimum value of 1 second is imposed.
+TransactionTimeout=15
+
+#
+# The maximum number of Berkeley DB locks available
+MaxDatabaseLocks=12000
diff --git a/src/com/sun/apoc/daemon/properties/os.properties.in b/src/com/sun/apoc/daemon/properties/os.properties.in
new file mode 100644
index 0000000..b7e1485
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/os.properties.in
@@ -0,0 +1,4 @@
+#
+# The daemon data directory ... where databases, logs etc. are kept
+#
+DataDir=@APOC_DATADIR@
diff --git a/src/com/sun/apoc/daemon/properties/policymgr.properties b/src/com/sun/apoc/daemon/properties/policymgr.properties
new file mode 100644
index 0000000..baeee3b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/policymgr.properties
@@ -0,0 +1,9 @@
+#-----------------------------#
+# Basic Configuration Example #
+#-----------------------------#
+
+#PROVIDER_URL = ldap://server1.freedesktop.org:389/o=mySuffixDn
+#AuthType=Anonymous
+#AuthDn=
+#Password=
+#ConnectTimeout=1
diff --git a/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java b/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java
new file mode 100644
index 0000000..e4a2522
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java
@@ -0,0 +1,58 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class AddListenerTransaction extends Transaction
+{
+ public AddListenerTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Altn001" );
+ mSession.addListeners(
+ ( ( AddListenerMessage )mRequest ).getComponentNames(),
+ ( ( AddListenerMessage )mRequest ).getClientData() );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Altn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java b/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java
new file mode 100644
index 0000000..0c545bf
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+import java.nio.*;
+
+public class ChangeDetectTransaction extends Transaction
+{
+ private ClientManager mClientManager;
+ private Cache mCache;
+ private UpdateAggregator mAggregator ;
+ private static final String[] sStringModel = new String[ 0 ];
+
+ public ChangeDetectTransaction( final ClientManager inClientManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ super( null, null);
+ mClientManager = inClientManager;
+ mCache = inCache;
+ mAggregator = inAggregator ;
+ }
+
+ protected void executeTransaction()
+ {
+ Session theSession = null;
+ try
+ {
+ APOCLogger.finer( "Cdtn001" );
+ //
+ // getLockedSession will try to lock 1 of the Session instances
+ // associated with database to be refreshed. If successful,
+ // the returned Session instance should be safe to use ( i.e. it
+ // wont be closed by someone else ) for the duration of the
+ // transaction. If unsuccessful, all relevant Session objects
+ // are already closed or closing so we can skip the change
+ // detection
+ //
+ theSession = getLockedSession();
+ if ( theSession != null )
+ {
+ final ArrayList theResults = mCache.changeDetect();
+ Session [] theSessions = mCache.getSessions();
+ int nbResults = theResults.size() ;
+
+ if ( nbResults > 0 )
+ {
+ for (int theIndex = 0 ; theIndex < nbResults ; ++ theIndex)
+ {
+ mAggregator.addUpdate(
+ theSessions,
+ (UpdateItem) theResults.get(theIndex)) ;
+ }
+ }
+ }
+ APOCLogger.finer( "Cdtn002" );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ChangeDetectTransaction",
+ "execute",
+ theException );
+ }
+ if ( theSession != null )
+ {
+ theSession.unlock();
+ }
+ }
+
+ protected boolean needSession() { return false; }
+
+ private Session getLockedSession()
+ {
+ Session theSession = null;
+ Session[] theSessions = mCache.getSessions();
+ if ( theSessions != null )
+ {
+ for ( int theIndex = 0; theIndex < theSessions.length; ++ theIndex )
+ {
+ if ( theSessions[ theIndex ].lock() )
+ {
+ theSession = theSessions[ theIndex ];
+ break;
+ }
+ }
+ }
+ return theSession;
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java b/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java
new file mode 100644
index 0000000..312bf52
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java
@@ -0,0 +1,76 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.transaction ;
+
+import com.sun.apoc.daemon.apocd.Client ;
+import com.sun.apoc.daemon.apocd.Session ;
+import com.sun.apoc.daemon.messaging.CreateSessionExtMessage ;
+import com.sun.apoc.daemon.messaging.Message ;
+import com.sun.apoc.daemon.misc.APOCException ;
+import com.sun.apoc.daemon.misc.APOCLogger ;
+import com.sun.apoc.daemon.misc.APOCSymbols ;
+
+class CreateSessionExtTransaction extends Transaction {
+ public CreateSessionExtTransaction(final Client aClient,
+ final Message aMessage) {
+ super(aClient, aMessage) ;
+ }
+ protected boolean needSession() { return false ; }
+ protected void executeTransaction() {
+ try {
+ APOCLogger.finer("Cstn001") ;
+ CreateSessionExtMessage message =
+ (CreateSessionExtMessage) mRequest ;
+
+ mSession = new Session(mClient, message.getUserId(),
+ message.getEntities()) ;
+ mClient.addSession(mSession) ;
+ setResponse(APOCSymbols.sSymRespSuccess, mSession.getSessionId()) ;
+ APOCLogger.finer("Cstn002") ;
+ }
+ catch (APOCException exception) {
+ setResponse(exception.getCode()) ;
+ APOCLogger.throwing("CreateSessionExtTransaction",
+ "executeTransaction", exception) ;
+ }
+ catch (Exception exception) {
+ setResponse(APOCSymbols.sSymRespUnknownFailure) ;
+ APOCLogger.throwing("CreateSessionExtTransaction",
+ "executeTransaction", exception) ;
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java b/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java
new file mode 100644
index 0000000..e759397
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java
@@ -0,0 +1,81 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class CreateSessionTransaction extends Transaction
+{
+ public CreateSessionTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected boolean needSession() { return false; }
+
+ protected void executeTransaction()
+ {
+ try
+ {
+ APOCLogger.finer( "Cstn001" );
+ final CreateSessionMessage theMessage =
+ ( CreateSessionMessage )mRequest;
+ mSession = new Session( mClient,
+ theMessage.getUserId(),
+ theMessage.getEntityId() );
+ mClient.addSession( mSession );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mSession.getSessionId() );
+ APOCLogger.finer( "Cstn002" );
+ }
+ catch ( APOCException theException )
+ {
+ setResponse( theException.getCode() );
+ APOCLogger.throwing( "CreateSessionTransaction",
+ "executeTransaction",
+ theException );
+ }
+ catch ( Exception theException )
+ {
+ setResponse( APOCSymbols.sSymRespUnknownFailure );
+ APOCLogger.throwing( "CreateSessionTransaction",
+ "executeTransaction",
+ theException );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java b/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java
new file mode 100644
index 0000000..4167cea
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class DestroySessionTransaction extends Transaction
+{
+ public DestroySessionTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Dstn001" );
+ mClient.closeSession( mSession );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Dstn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java b/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java
new file mode 100644
index 0000000..4cf92a9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+
+public class GarbageCollectTransaction extends Transaction
+{
+ private final Database mDatabase;
+
+ public GarbageCollectTransaction( final Database inDatabase )
+ {
+ super( null, null );
+ mDatabase = inDatabase;
+ }
+
+ protected void executeTransaction()
+ {
+ try
+ {
+ APOCLogger.finer( "Gctn001" );
+ mDatabase.beginTransaction();
+ boolean shouldCollect =
+ Timestamp.getMillis( mDatabase.getLastRead() ) <=
+ ( Timestamp.getMillis( Timestamp.getTimestamp() ) -
+ ( DaemonConfig.getIntProperty( DaemonConfig.sTimeToLive ) *
+ 60000 ) );
+ mDatabase.endTransaction();
+ mDatabase.close( 0 );
+ if ( shouldCollect )
+ {
+ LocalDatabaseFactory.getInstance().deleteDatabase( mDatabase );
+ }
+ APOCLogger.finer( "Gctn002" );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "GarbageCollectTransaction",
+ "execute",
+ theException );
+ }
+ }
+
+ protected boolean needSession() { return false; }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ListTransaction.java b/src/com/sun/apoc/daemon/transaction/ListTransaction.java
new file mode 100644
index 0000000..404f0ae
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ListTransaction.java
@@ -0,0 +1,82 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+class ListTransaction extends Transaction
+{
+ public ListTransaction( final Client inClient, final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected void executeTransaction()
+ {
+ APOCLogger.finer( "Lstn001" );
+ StringBuffer theBuffer = null;
+ final Cache [] theCaches = mSession.getCaches();
+ final HashSet theSet = new HashSet();
+
+ for (int theIndex = 0 ; theIndex < theCaches.length ; ++ theIndex)
+ {
+ theSet.addAll(theCaches [theIndex].list());
+ }
+ if ( theSet != null && theSet.size() > 0 )
+ {
+ final String[] theNames =
+ ( String[] )theSet.toArray( new String[ 0 ] );
+ theBuffer = new StringBuffer();
+ for ( int theIndex = 0; theIndex < theNames.length; theIndex ++)
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+ .append( theNames[ theIndex ] )
+ .append( "</" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" );
+ }
+ }
+ APOCLogger.finer( "Lstn002" );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mRequest.getSessionId(),
+ theBuffer != null ? theBuffer.toString() : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ReadTransaction.java b/src/com/sun/apoc/daemon/transaction/ReadTransaction.java
new file mode 100644
index 0000000..44d0d07
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ReadTransaction.java
@@ -0,0 +1,86 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+class ReadTransaction extends Transaction
+{
+ public ReadTransaction( final Client inClient, final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected void executeTransaction()
+ {
+ APOCLogger.finer( "Rdtn001" );
+ StringBuffer theBuffer = null;
+ final String theComponentName =
+ ( String )( ( ReadMessage )mRequest )
+ .getComponentNames().elementAt( 0 );
+ final Cache [] theCaches = mSession.getCaches();
+ final ArrayList theResults = new ArrayList();
+
+ for (int theIndex = 0 ; theIndex < theCaches.length ; ++ theIndex)
+ {
+ theResults.addAll(theCaches [theIndex].read(theComponentName));
+ }
+ if ( theResults.size() > 0 )
+ {
+ theBuffer = new StringBuffer();
+ final Iterator theIterator = theResults.iterator();
+ while ( theIterator.hasNext() )
+ {
+ CacheReadResult theResult = (CacheReadResult)theIterator.next();
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamLayer )
+ .append( "><![CDATA[" )
+ .append( theResult.mTimestamp )
+ .append( theResult.mData )
+ .append( "]]></" )
+ .append( APOCSymbols.sParamLayer )
+ .append( ">" );
+ }
+ }
+ APOCLogger.finer( "Rdtn002" );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mRequest.getSessionId(),
+ theBuffer != null ? theBuffer.toString() : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java b/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java
new file mode 100644
index 0000000..2d346c4
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java
@@ -0,0 +1,57 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class RemoveListenerTransaction extends Transaction
+{
+ public RemoveListenerTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Rltn001" );
+ mSession.removeListeners(
+ ( ( RemoveListenerMessage )mRequest ).getComponentNames() );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Rltn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/Transaction.java b/src/com/sun/apoc/daemon/transaction/Transaction.java
new file mode 100644
index 0000000..59fee20
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/Transaction.java
@@ -0,0 +1,148 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+public abstract class Transaction
+{
+ protected final Client mClient;
+ protected Session mSession;
+ protected final Message mRequest;
+ protected Message mResponse;
+ private Thread mThread;
+ private Object mThreadLock = new Object();
+ private long mStartTime;
+
+ public Transaction( final Client inClient, final Message inRequest )
+ {
+ mClient = inClient;
+ mRequest = inRequest;
+ if ( inClient != null && inRequest != null )
+ {
+ mSession = inClient.getSession( mRequest.getSessionId() );
+ }
+ }
+
+ public Message execute()
+ {
+ if ( ! needSession() || mSession != null )
+ {
+ try
+ {
+ beginTransaction();
+ executeTransaction();
+ endTransaction();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Transaction", "execute", theException );
+ setResponse( APOCSymbols.sSymRespUnknownFailure );
+ }
+ }
+ else
+ {
+ setResponse( APOCSymbols.sSymRespInvalidSessionId );
+ }
+ return mResponse;
+ }
+
+ public long getDuration()
+ {
+ return System.currentTimeMillis() - mStartTime;
+ }
+
+ public void interrupt()
+ {
+ synchronized( mThreadLock )
+ {
+ if ( mThread != null )
+ {
+ mThread.interrupt();
+ mThread = null;
+ }
+ }
+ }
+
+ protected boolean needSession()
+ {
+ return true;
+ }
+
+ protected void beginTransaction()
+ {
+ mStartTime = System.currentTimeMillis();
+ setThread( Thread.currentThread() );
+ TransactionFactory.getInstance().addTransaction( this );
+ }
+ protected abstract void executeTransaction();
+ protected void endTransaction()
+ {
+ setThread( null );
+ TransactionFactory.getInstance().removeTransaction( this );
+ }
+
+ protected void setResponse( final int inResponseType )
+ {
+ setResponse( inResponseType, mRequest.getSessionId(), null );
+ }
+
+ protected void setResponse( final int inResponseType,
+ final String inSessionId )
+ {
+ setResponse( inResponseType, inSessionId, null );
+ }
+
+ protected void setResponse( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ mResponse = MessageFactory.createResponse( inResponseType,
+ inSessionId,
+ inResponseMessage );
+ }
+
+ private void setThread( final Thread inThread )
+ {
+ synchronized( mThreadLock )
+ {
+ mThread = inThread;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/TransactionFactory.java b/src/com/sun/apoc/daemon/transaction/TransactionFactory.java
new file mode 100644
index 0000000..3418d7b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/TransactionFactory.java
@@ -0,0 +1,181 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+public class TransactionFactory
+{
+
+ private static TransactionFactory sInstance;
+ private static final Transaction[] sTransactionModel =
+ new Transaction[ 0 ];
+ //private static long sTransactionTimeout = 30000;
+ private static long sTransactionTimeout = 10000;
+ private final HashSet mTransactions = new HashSet();
+ private final DaemonTimerTask mTransactionInterrupter =
+ new DaemonTimerTask( new TransactionInterrupter() );
+
+ public void addTransaction( final Transaction inTransaction )
+ {
+ synchronized( mTransactions )
+ {
+ if ( mTransactions.size() == 0 )
+ {
+ mTransactionInterrupter.setPeriod( sTransactionTimeout );
+ }
+ mTransactions.add( inTransaction );
+ }
+ }
+
+ public ChangeDetectTransaction createChangeDetectTransaction(
+ final ClientManager inClientManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ return new ChangeDetectTransaction( inClientManager,
+ inCache, inAggregator );
+ }
+
+ public GarbageCollectTransaction createGarbageCollectTransaction(
+ final Database inDatabase )
+ {
+ return new GarbageCollectTransaction( inDatabase );
+ }
+
+ public Transaction createTransaction( final Client inClient,
+ final Message inMessage )
+ {
+ Transaction theTransaction = null;
+ switch ( inMessage.getName() )
+ {
+ case APOCSymbols.sSymReqRead:
+ theTransaction = new ReadTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqAddListener:
+ theTransaction =
+ new AddListenerTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqCreateSession:
+ theTransaction =
+ new CreateSessionTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqCreateSessionExt:
+ theTransaction =
+ new CreateSessionExtTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqDestroySession:
+ theTransaction =
+ new DestroySessionTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqRemoveListener:
+ theTransaction =
+ new RemoveListenerTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqList:
+ theTransaction =
+ new ListTransaction( inClient, inMessage );
+ break;
+
+ default:
+ break;
+ }
+ return theTransaction;
+ }
+
+ public static TransactionFactory getInstance()
+ {
+ if ( sInstance == null )
+ {
+ sInstance = new TransactionFactory();
+ }
+ return sInstance;
+ }
+
+ public void removeTransaction( final Transaction inTransaction )
+ {
+ synchronized( mTransactions )
+ {
+ if ( mTransactions.size() == 1 )
+ {
+ mTransactionInterrupter.cancel();
+ }
+ mTransactions.remove( inTransaction );
+ }
+ }
+
+ private TransactionFactory(){}
+
+ class TransactionInterrupter implements Runnable
+ {
+ public void run()
+ {
+ synchronized( mTransactions )
+ {
+ Transaction[] theTransactions = null;
+ if ( mTransactions.size() > 0 )
+ {
+ theTransactions =
+ ( Transaction[] )mTransactions.toArray( sTransactionModel);
+ }
+ if ( theTransactions != null && theTransactions.length > 0 )
+ {
+ for ( int theIndex = 0;
+ theIndex < theTransactions.length;
+ ++ theIndex )
+ {
+ if ( theTransactions[ theIndex ].getDuration() >
+ sTransactionTimeout )
+ {
+ theTransactions[ theIndex ].interrupt();
+ removeTransaction( theTransactions[ theIndex ] );
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ChannelManager.java b/src/com/sun/apoc/daemon/transport/ChannelManager.java
new file mode 100644
index 0000000..f550350
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ChannelManager.java
@@ -0,0 +1,414 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.util.logging.*;
+
+public class ChannelManager extends Thread implements ConfigEventListener
+{
+ private Selector mSelector;
+ private ServerSocketChannel mChannel;
+ private final HashSet mRegisteringChannels =
+ new HashSet();
+ private final HashSet mDeRegisteringChannels =
+ new HashSet();
+ private final Object mLock = new Object();
+ private int mMaxClientChannels =
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxClientConnections );
+ private final HashSet mClientChannelEventListeners = new HashSet();
+ private int mChannelCount = 0;
+ private boolean mTerminate = false;
+ private static final byte sReject = 0;
+ private static final byte[] sAcceptByte = { 1 };
+ private static final ByteBuffer sAccept =
+ ( ByteBuffer )ByteBuffer.wrap( sAcceptByte );
+
+ public ChannelManager()
+ throws APOCException
+ {
+ try
+ {
+ initThread();
+ initChannel();
+ DaemonConfig.addConfigEventListener( this );
+ }
+ catch( IOException theException )
+ {
+ throw new APOCException(
+ APOCSymbols.sSymCreateServerChannelFailed,
+ theException );
+ }
+ }
+
+ public void addClientChannelEventListener(
+ final ClientChannelEventListener inListener )
+ {
+ if ( inListener != null )
+ {
+ synchronized( mClientChannelEventListeners )
+ {
+ mClientChannelEventListeners.add( inListener );
+ }
+ }
+ }
+
+ public void closeClientChannels()
+ {
+ final Set theKeys = mSelector.keys();
+ if ( theKeys != null )
+ {
+ final Iterator theIterator = theKeys.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ if ( theKey.isValid() )
+ {
+ try
+ {
+ theKey.channel().close();
+ }
+ catch( IOException theException )
+ {}
+ }
+ }
+ }
+ }
+
+ public void closeChannels()
+ {
+ closeClientChannels();
+ closeServerChannel();
+ }
+
+ public void onConfigEvent()
+ {
+ setMaxClientChannels();
+ }
+
+ public void removeClientChannelEventListener(
+ final ClientChannelEventListener inListener )
+ {
+ if ( inListener != null )
+ {
+ synchronized( mClientChannelEventListeners )
+ {
+ mClientChannelEventListeners.remove( inListener );
+ }
+ }
+ }
+
+ public void run()
+ {
+ APOCLogger.fine( "Chmr001" );
+ while ( ! shouldTerminate() )
+ {
+ try
+ {
+ selectChannels();
+ registerChannels();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ChannelManager", "run", theException );
+ break;
+ }
+ }
+ APOCLogger.fine( "Chmr003" );
+ }
+
+ public void terminate()
+ {
+ synchronized( mLock )
+ {
+ mTerminate = true;
+ }
+ mSelector.wakeup();
+ }
+
+ void closeClientChannel( final ClientChannel inChannel )
+ {
+ inChannel.close();
+ notifyClosed( inChannel );
+ synchronized( mLock )
+ {
+ -- mChannelCount;
+ }
+ }
+
+ void registerForSelection( final ClientChannel inChannel,boolean inRegister)
+ {
+ final HashSet theSet = inRegister ?
+ mRegisteringChannels : mDeRegisteringChannels;
+ synchronized( theSet )
+ {
+ theSet. add( inChannel.getSocketChannel().keyFor( mSelector ) );
+ mSelector.wakeup();
+ try
+ {
+ theSet.wait();
+ }
+ catch( Exception theException )
+ {}
+ }
+ }
+
+ private void acceptableKey( final SelectionKey inKey )
+ {
+ SocketChannel theSocketChannel = null;
+ try
+ {
+ theSocketChannel =
+ ( ( ServerSocketChannel )inKey.channel() ).accept();
+ if ( ! testMaxChannels() && theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.socket()
+ .getOutputStream().write( sReject );
+ theSocketChannel.close();
+ }
+ catch( Exception theException ){}
+ return;
+ }
+ if ( theSocketChannel.
+ socket().
+ getInetAddress().
+ isLoopbackAddress() )
+ {
+ theSocketChannel.configureBlocking( false );
+ final SelectionKey theClientKey =
+ theSocketChannel.register(
+ mSelector,
+ SelectionKey.OP_READ );
+ ClientChannel theClientChannel =
+ new ClientChannel( theSocketChannel, this );
+ theClientKey.attach( theClientChannel );
+ synchronized( mLock )
+ {
+ ++ mChannelCount;
+ }
+ theClientChannel.write( sAccept );
+ sAccept.flip();
+ }
+ }
+ catch( IOException theException )
+ {
+ if ( theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.close();
+ }
+ catch( Exception ignore )
+ {}
+ }
+ APOCLogger.throwing( "ChannelManager",
+ "acceptableKey",
+ theException );
+ }
+ }
+
+ private void closeServerChannel()
+ {
+ try
+ {
+ mSelector.close();
+ mChannel.close();
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "ClientManager", "close", theException );
+ }
+ }
+
+ private int getMaxClientChannels()
+ {
+ synchronized( mLock )
+ {
+ return mMaxClientChannels;
+ }
+ }
+
+ private void initChannel()
+ throws IOException
+ {
+ mSelector = Selector.open();
+ mChannel = ServerSocketChannel.open();
+ mChannel.configureBlocking( false );
+ mChannel.socket().bind(
+ new InetSocketAddress(
+ DaemonConfig.getIntProperty( DaemonConfig.sDaemonPort ) ) );
+ mChannel.register( mSelector, SelectionKey.OP_ACCEPT );
+ }
+
+ private void initThread()
+ {
+ setName( "ChannelManager" );
+ setDaemon( true );
+ }
+
+ private void notifyClosed( final ClientChannel inClientChannel )
+ {
+ final Iterator theIterator = mClientChannelEventListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( ClientChannelEventListener )theIterator.next() ).onClosed(
+ inClientChannel );
+ }
+ }
+
+ private void notifyPending( final ClientChannel inClientChannel )
+ {
+ final Iterator theIterator = mClientChannelEventListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( ClientChannelEventListener )theIterator.next() ).onPending(
+ inClientChannel );
+ }
+ }
+
+ private void readableKey( final SelectionKey inKey )
+ {
+ inKey.interestOps(
+ inKey.interestOps() &
+ ( ~ SelectionKey.OP_READ ) );
+ notifyPending( ( ClientChannel )inKey.attachment() );
+ }
+
+ private void registerChannels()
+ {
+ synchronized( mRegisteringChannels )
+ {
+ if ( mRegisteringChannels.size() > 0 )
+ {
+ final Iterator theIterator = mRegisteringChannels.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ theKey.interestOps( theKey.interestOps() |
+ SelectionKey.OP_READ );
+ }
+ mRegisteringChannels.clear();
+ mRegisteringChannels.notifyAll();
+ }
+ }
+ synchronized( mDeRegisteringChannels )
+ {
+ if ( mDeRegisteringChannels.size() > 0 )
+ {
+ final Iterator theIterator = mDeRegisteringChannels.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ theKey.interestOps( theKey.interestOps() &
+ ( ~ SelectionKey.OP_READ ) );
+ }
+ }
+ mDeRegisteringChannels.clear();
+ mDeRegisteringChannels.notifyAll();
+ }
+ }
+
+ private void selectChannels()
+ throws IOException
+ {
+ if ( mSelector.select() > 0 )
+ {
+ final Iterator theIterator = mSelector.selectedKeys().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey = ( SelectionKey )theIterator.next();
+ theIterator.remove();
+ if ( theKey.isAcceptable() )
+ {
+ acceptableKey( theKey );
+ }
+ if ( theKey.isReadable() )
+ {
+ readableKey( theKey );
+ }
+ }
+ }
+ }
+
+ private void setMaxClientChannels()
+ {
+ synchronized( mLock )
+ {
+ mMaxClientChannels =
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections );
+ }
+ mSelector.wakeup();
+ }
+
+ private boolean shouldTerminate()
+ {
+ synchronized( mLock )
+ {
+ return mTerminate;
+ }
+ }
+
+ private boolean testMaxChannels()
+ {
+ boolean bMoreChannelsAllowed = false;
+ int theMaxClientChannels = getMaxClientChannels();
+ if ( theMaxClientChannels > 0 )
+ {
+ synchronized( mLock )
+ {
+ bMoreChannelsAllowed = theMaxClientChannels > mChannelCount;
+ }
+ }
+ if ( ! bMoreChannelsAllowed )
+ {
+ APOCLogger.warning( "Chmr002",
+ String.valueOf( theMaxClientChannels ) );
+ }
+ return bMoreChannelsAllowed;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ClientChannel.java b/src/com/sun/apoc/daemon/transport/ClientChannel.java
new file mode 100644
index 0000000..87ae738
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ClientChannel.java
@@ -0,0 +1,150 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+
+public class ClientChannel
+{
+ private SocketChannel mChannel;
+ private ChannelManager mManager = null;
+
+ private static int sSoTimeout =
+ DaemonConfig.getIntProperty( DaemonConfig.sConnectionReadTimeout );
+
+ public ClientChannel( final SocketChannel inChannel,
+ final ChannelManager inManager )
+ throws IOException
+ {
+ this( inChannel );
+ mManager = inManager;
+ }
+
+ public ClientChannel( final SocketChannel inChannel )
+ throws IOException
+ {
+ initChannel( inChannel );
+ }
+
+ public SocketChannel getSocketChannel() { return mChannel; }
+
+ public void registerForSelection( boolean inRegister )
+ {
+ mManager.registerForSelection( this, inRegister );
+ }
+
+ public long read( final ByteBuffer outBuffer )
+ throws IOException
+ {
+ long theByteCount = 0;
+ while ( theByteCount == 0 )
+ {
+ try
+ {
+ theByteCount = mChannel.read( outBuffer );
+ if ( theByteCount == 0 )
+ {
+ Thread.currentThread().yield();
+ }
+ }
+ catch( IOException theException )
+ {
+ theByteCount = -1;
+ break;
+ }
+ }
+ if ( theByteCount == -1 )
+ {
+ APOCLogger.finest( "Clch002" );
+ if ( mManager != null )
+ {
+ mManager.closeClientChannel( this );
+ }
+ throw new IOException();
+ }
+ return theByteCount;
+ }
+
+ public void write( final ByteBuffer inBuffer )
+ {
+ try
+ {
+ while ( inBuffer.hasRemaining() )
+ {
+ mChannel.write( inBuffer );
+ }
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "ClientChannel", "write", theException );
+ if ( mManager != null )
+ {
+ mManager.closeClientChannel( this );
+ }
+ }
+ }
+
+ public void close()
+ {
+ try
+ {
+ if ( mChannel != null )
+ {
+ mChannel.close();
+ mChannel = null;
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ClientChannel", "close", theException );
+ }
+ }
+
+ private void initChannel( final SocketChannel inChannel )
+ throws IOException
+ {
+ mChannel = inChannel;
+ final Socket theSocket = mChannel.socket();
+ theSocket.setSoLinger( false, 0 );
+ theSocket.setSoTimeout( sSoTimeout );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java b/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java
new file mode 100644
index 0000000..dfef31c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+public interface ClientChannelEventListener
+{
+ public void onPending( ClientChannel inClientChannel );
+ public void onClosed( ClientChannel inClientChannel );
+}