ServerResourceManager.java
/*
** Module : ServerResourceManager.java
** Abstract : Management of server OS resources.
**
** Copyright (c) 2022-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
** 001 CA 20220515 Created initial version.
** RFB 20220524 Fixed minor javadoc error.
** CA 20220918 Allow legacy client sockets to be ran on FWD server instead of FWD client.
** 002 HC 20230427 Implemented server-side file-system resource. File operations performed on
** client can be optionally performed directly on server without the expensive
** remote call.
** 003 HC 20230517 Implemented server-side web service calling.
** 004 GBB 20240826 Saving instantiated resources to an instance fields of type map
** (the manager is context local). Adding initializeEnvironments.
** 005 GBB 20240912 Adding support for types mail, launcher and streams.
** Renaming ServerSideResourceManager to ServerResourceManager.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.util.osresource;
import com.goldencode.p2j.library.*;
import com.goldencode.p2j.net.*;
import com.goldencode.p2j.ui.*;
import com.goldencode.p2j.ui.chui.*;
import com.goldencode.p2j.ui.client.*;
import com.goldencode.p2j.util.*;
import com.goldencode.util.*;
import java.util.concurrent.atomic.*;
/**
* Management of OS resources on server-side.
* <p>
* This allows initialization and creation of network objects, so that the client-side can call back (if needed)
* on the server-side, to use these resources.
*/
class ServerResourceManager
extends OSResourceManager
{
/** Flag required to initialize the remote server-side resources only once per JVM. */
private static final AtomicBoolean IS_INIT = new AtomicBoolean();
/**
* Package-private constructor.
*/
ServerResourceManager()
{
synchronized (ServerResourceManager.class)
{
// the native api requires the client to call the remote server even with server-side resources,
// so network server interfaces should be registered
if (!IS_INIT.get())
{
if (isServerSide(OsResourceType.MEMPTR))
{
initializeMemptrResource();
}
if (isServerSide(OsResourceType.LIBRARY))
{
initializeLibraryResource();
}
if (isServerSide(OsResourceType.SOCKET))
{
initializeSocketResource();
}
IS_INIT.set(true);
}
}
}
/**
* Initialize the OS {@link OsResourceType#MEMPTR} resource.
* <p>
* If the {@link #isServerSide(OsResourceType)} memptr is server-side, the {@link MemoryDaemon} is proxied over
* the network and this returns a local proxy, to be used on server-side.
*
* @return The {@link LowLevelBuffer} network or local object.
*/
@Override
LowLevelBuffer initializeMemptr()
{
LowLevelBuffer memptr = (LowLevelBuffer) resources.get(OsResourceType.MEMPTR);
if (memptr != null)
{
return memptr;
}
if (isServerSide(OsResourceType.MEMPTR))
{
new MemoryDaemon(true);
memptr = (LowLevelBuffer) RemoteObject.obtainLocalInstance(LowLevelBuffer.class, true);
}
else
{
memptr = (LowLevelBuffer) RemoteObject.obtainInstance(LowLevelBuffer.class, true);
}
resources.put(OsResourceType.MEMPTR, memptr);
return memptr;
}
/**
* Initialize the OS {@link OsResourceType#LIBRARY} resource.
* <p>
* If the {@link #isServerSide(OsResourceType)} library is server-side, the {@link LibraryDaemon} is proxied over
* the network and this returns a local proxy, to be used on server-side.
*
* @return The {@link NativeAPICaller} network or local object.
*/
@Override
NativeAPICaller initializeLibrary()
{
NativeAPICaller lib = (NativeAPICaller) resources.get(OsResourceType.LIBRARY);
if (lib != null)
{
return lib;
}
if (isServerSide(OsResourceType.LIBRARY))
{
new LibraryDaemon(true);
lib = (NativeAPICaller) RemoteObject.obtainLocalInstance(NativeAPICaller.class, true);
}
else
{
lib = (NativeAPICaller) RemoteObject.obtainInstance(NativeAPICaller.class, true);
}
resources.put(OsResourceType.LIBRARY, lib);
return lib;
}
/**
* Initialize the OS {@link OsResourceType#SOCKET} resource.
* <p>
* If the {@link #isServerSide(OsResourceType)}} client-socket is server-side, the {@link LowLevelSocket} is
* proxied over the network and this returns a local proxy, to be used on server-side.
*
* @return The {@link LowLevelSocket} network or local object.
*/
@Override
LowLevelSocket initializeSocket()
{
LowLevelSocket socket = (LowLevelSocket) resources.get(OsResourceType.SOCKET);
if (socket != null)
{
return socket;
}
if (isServerSide(OsResourceType.SOCKET))
{
new LowLevelSocketImpl(true);
socket = (LowLevelSocket) RemoteObject.obtainLocalInstance(LowLevelSocket.class, true);
}
else
{
socket = (LowLevelSocket) RemoteObject.obtainInstance(LowLevelSocket.class, true);
}
resources.put(OsResourceType.SOCKET, socket);
return socket;
}
/**
* Initialize the OS {@link OsResourceType#FILESYSTEM} resource.
* <p>
* If the {@link #isServerSide(OsResourceType)} file system is server-side, the {@link FileSystem} is
* proxied over the network and this returns a local proxy, to be used on server-side.
*
* @return The {@link FileSystem} network or local object.
*/
@Override
FileSystem initializeFileSystem()
{
FileSystem fs = (FileSystem) resources.get(OsResourceType.FILESYSTEM);
if (fs != null)
{
return fs;
}
if (isServerSide(OsResourceType.FILESYSTEM))
{
FileSystemDaemon.getInstance(true, true);
fs = (FileSystem) RemoteObject.obtainLocalInstance(FileSystem.class, true);
}
else
{
fs = (FileSystem) RemoteObject.obtainInstance(FileSystem.class, true);
}
resources.put(OsResourceType.FILESYSTEM, fs);
return fs;
}
/**
* Initialize the OS {@link OsResourceType#WEBSERVICE} resource.
*
* @return The {@link WebService} network or local object.
*/
@Override
WebService initializeWebService()
{
WebService ws = (WebService) resources.get(OsResourceType.WEBSERVICE);
if (ws != null)
{
return ws;
}
if (isServerSide(OsResourceType.WEBSERVICE))
{
WebServiceImpl.getInstance(true);
ws = (WebService) RemoteObject.obtainLocalInstance(WebService.class, true);
}
else
{
ws = (WebService) RemoteObject.obtainInstance(WebService.class, true);
}
resources.put(OsResourceType.WEBSERVICE, ws);
return ws;
}
/**
/**
* Get the OS {@link OsResourceType#ENVIRONMENTS} resource.
*
* @return The {@link EnvironmentAccessor} network or local object.
*/
@Override
EnvironmentAccessor initializeEnvironments()
{
EnvironmentAccessor env = (EnvironmentAccessor) resources.get(OsResourceType.ENVIRONMENTS);
if (env != null)
{
return env;
}
if (isServerSide(OsResourceType.ENVIRONMENTS))
{
String storageId = SessionUtils.getStorageId();
String fwdUser = com.goldencode.p2j.security.SecurityManager.getInstance().getUserId();
ClientStorage clientStorage = new ClientStorageImpl(new UserPreferences(storageId, fwdUser));
// create the network server for the server-side environments usage
new EnvironmentDaemon(EnvironmentOps.getVersion().toStringMessage(),
true,
PlatformHelper.isUnderWindowsFamily(),
clientStorage);
env = (EnvironmentAccessor) RemoteObject.obtainLocalInstance(EnvironmentAccessor.class, true);
}
else
{
env = (EnvironmentAccessor) RemoteObject.obtainInstance(EnvironmentAccessor.class, true);
}
resources.put(OsResourceType.ENVIRONMENTS, env);
return env;
}
/**
* Get the OS {@link OsResourceType#MAIL} resource.
*
* @return The {@link RemoteEmailSender} network or local object.
*/
@Override
RemoteEmailSender initializeEmailSender()
{
RemoteEmailSender mailSender = (RemoteEmailSender) resources.get(OsResourceType.MAIL);
if (mailSender != null)
{
return mailSender;
}
if (isServerSide(OsResourceType.MAIL))
{
// create the network server for the server-side mail sender usage
new EmailDaemon(true);
mailSender = (RemoteEmailSender) RemoteObject.obtainLocalInstance(RemoteEmailSender.class, true);
}
else
{
mailSender = (RemoteEmailSender) RemoteObject.obtainInstance(RemoteEmailSender.class, true);
}
resources.put(OsResourceType.MAIL, mailSender);
return mailSender;
}
/**
* Initialize the OS {@link OsResourceType#LAUNCHER} resource.
*
* @return The {@link Launcher} network or local object.
*/
@Override
Launcher initializeProcessLauncher()
{
Launcher launcher = (Launcher) resources.get(OsResourceType.LAUNCHER);
if (launcher != null)
{
return launcher;
}
if (isServerSide(OsResourceType.LAUNCHER))
{
// create the network server for the server-side process launching
new ProcessDaemon(new ServerSideTerminal(), true);
launcher = (Launcher) RemoteObject.obtainLocalInstance(Launcher.class, true);
}
else
{
launcher = (Launcher) RemoteObject.obtainInstance(Launcher.class, true);
}
resources.put(OsResourceType.LAUNCHER, launcher);
return launcher;
}
/**
* Initialize the OS {@link OsResourceType#STREAMS} resource.
*
* @return The {@link StreamDaemon} network or local object.
*/
@Override
StreamHelper initializeStreamHelper()
{
StreamHelper streams = (StreamHelper) resources.get(OsResourceType.STREAMS);
if (streams != null)
{
return streams;
}
if (isServerSide(OsResourceType.STREAMS))
{
streams = new StreamDaemon(new ServerSideTerminal());
}
else
{
streams = (StreamHelper) RemoteObject.obtainInstance(StreamHelper.class, true);
}
resources.put(OsResourceType.STREAMS, streams);
return streams;
}
/**
* Initialize the {@link OsResourceType#MEMPTR} resource on server-side, by creating a network proxy for the
* {@link MemoryDaemon}.
*/
private static void initializeMemptrResource()
{
// create the network server for the server-side memory usage
new MemoryDaemon(false);
// load the FWD native libraries
LibraryManager.init();
}
/**
* Initialize the {@link OsResourceType#LIBRARY} resource on server-side, by creating a network proxy for the
* {@link LibraryDaemon}.
*/
private static void initializeLibraryResource()
{
// create the network server for the server-side library usage
new LibraryDaemon(false);
// load the FWD native libraries
LibraryManager.init();
}
/**
* Initialize the {@link OsResourceType#SOCKET} resource on server-side, by creating a network proxy for the
* {@link LowLevelSocket}.
*/
private static void initializeSocketResource()
{
new LowLevelSocketImpl(false);
}
}