import java.util.List;
import java.util.Locale;
-import java.util.Map;
+import java.util.UUID;
import javax.security.auth.Subject;
/** Get the CMS session of this subject. */
CmsSession getCmsSession(Subject subject);
- CmsState getCmsState();
+ CmsEventBus getCmsEventBus();
- void sendEvent(String topic, Map<String, Object> event);
+ /** A new time based {@link UUID} (v1) using the current time */
+ UUID timeUUID();
- void addEventSubscriber(String topic, CmsEventSubscriber eventSubscriber);
-
- void removeEventSubscriber(String topic, CmsEventSubscriber eventSubscriber);
}
--- /dev/null
+package org.argeo.api.cms;
+
+import java.util.Map;
+
+public interface CmsEventBus {
+ void sendEvent(String topic, Map<String, Object> event);
+
+ void addEventSubscriber(String topic, CmsEventSubscriber eventSubscriber);
+
+ void removeEventSubscriber(String topic, CmsEventSubscriber eventSubscriber);
+
+}
/** A running node process. */
public interface CmsState {
+ String getHostname();
+
Long getAvailableSince();
UUID getUuid();
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
-import org.argeo.api.cms.CmsContext;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsEventSubscriber;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
private BundleContext bc = FrameworkUtil.getBundle(TestEndpoint.class).getBundleContext();
private RemoteEndpoint.Basic remote;
- private CmsContext cmsContext;
+ private CmsEventBus cmsEventBus;
// private String topic = "cms";
@OnOpen
public void onOpen(Session session, @PathParam("topic") String topic) {
if (bc != null) {
- cmsContext = bc.getService(bc.getServiceReference(CmsContext.class));
- cmsContext.addEventSubscriber(topic, this);
+ cmsEventBus = bc.getService(bc.getServiceReference(CmsEventBus.class));
+ cmsEventBus.addEventSubscriber(topic, this);
}
remote = session.getBasicRemote();
@OnClose
public void onClose(@PathParam("topic") String topic) {
- cmsContext.removeEventSubscriber(topic, this);
+ cmsEventBus.removeEventSubscriber(topic, this);
}
@Override
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Map;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
-import javax.websocket.DeploymentException;
-import javax.websocket.server.ServerContainer;
-import javax.websocket.server.ServerEndpointConfig;
-import com.sun.net.httpserver.Authenticator;
-import com.sun.net.httpserver.HttpContext;
-
-import org.argeo.api.cms.CmsState;
-import org.argeo.cms.CmsDeployProperty;
-import org.argeo.cms.websocket.server.CmsWebSocketConfigurator;
-import org.argeo.cms.websocket.server.TestEndpoint;
+
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
-import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
public class CmsJettyServer extends JettyHttpServer {
private static final String CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
// WebSocket
// private ServerContainer wsServerContainer;
- private ServerEndpointConfig.Configurator wsEndpointConfigurator;
-
- private CmsState cmsState;
+// private ServerEndpointConfig.Configurator wsEndpointConfigurator;
// private Authenticator defaultAuthenticator;
@Override
protected void configureRootContextHandler(ServletContextHandler servletContextHandler) throws ServletException {
addServlets(servletContextHandler);
- enableWebSocket(servletContextHandler);
+// enableWebSocket(servletContextHandler);
}
// return httpContext;
// }
- protected void enableWebSocket(ServletContextHandler servletContextHandler) {
- String webSocketEnabled = getDeployProperty(CmsDeployProperty.WEBSOCKET_ENABLED);
- // web socket
- if (webSocketEnabled != null && webSocketEnabled.equals(Boolean.toString(true))) {
-// JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
-//
-// @Override
-// public void accept(ServletContext servletContext, ServerContainer serverContainer)
-// throws DeploymentException {
-//// wsServerContainer = serverContainer;
-//
-// CmsWebSocketConfigurator wsEndpointConfigurator = new CmsWebSocketConfigurator();
-//
-// ServerEndpointConfig config = ServerEndpointConfig.Builder
-// .create(TestEndpoint.class, "/ws/test/events/{topic}").configurator(wsEndpointConfigurator)
-// .build();
-// try {
-// serverContainer.addEndpoint(config);
-// } catch (DeploymentException e) {
-// throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
-// }
-// }
-// });
- }
- }
-
- protected String getDeployProperty(CmsDeployProperty deployProperty) {
- return cmsState.getDeployProperty(deployProperty.getProperty());
- }
-
- public void setCmsState(CmsState cmsState) {
- this.cmsState = cmsState;
- }
+// protected void enableWebSocket(ServletContextHandler servletContextHandler) {
+// String webSocketEnabled = getDeployProperty(CmsDeployProperty.WEBSOCKET_ENABLED);
+// // web socket
+// if (webSocketEnabled != null && webSocketEnabled.equals(Boolean.toString(true))) {
+//// JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
+////
+//// @Override
+//// public void accept(ServletContext servletContext, ServerContainer serverContainer)
+//// throws DeploymentException {
+////// wsServerContainer = serverContainer;
+////
+//// CmsWebSocketConfigurator wsEndpointConfigurator = new CmsWebSocketConfigurator();
+////
+//// ServerEndpointConfig config = ServerEndpointConfig.Builder
+//// .create(TestEndpoint.class, "/ws/test/events/{topic}").configurator(wsEndpointConfigurator)
+//// .build();
+//// try {
+//// serverContainer.addEndpoint(config);
+//// } catch (DeploymentException e) {
+//// throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
+//// }
+//// }
+//// });
+// }
+// }
// public void setDefaultAuthenticator(Authenticator defaultAuthenticator) {
// this.defaultAuthenticator = defaultAuthenticator;
import javax.servlet.ServletException;
import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.CmsState;
import org.argeo.cms.CmsDeployProperty;
import org.argeo.util.http.HttpServerUtils;
import org.eclipse.jetty.http.UriCompliance;
protected ServerConnector httpConnector;
protected ServerConnector httpsConnector;
- private InetSocketAddress address;
+ private InetSocketAddress httpAddress;
+ private InetSocketAddress httpsAddress;
private ThreadPoolExecutor executor;
private boolean started;
+ private CmsState cmsState;
+
@Override
public void bind(InetSocketAddress addr, int backlog) throws IOException {
throw new UnsupportedOperationException();
@Override
public InetSocketAddress getAddress() {
- return address;
+ return httpAddress;
}
@Override
return httpsConfigurator;
}
-
-
protected void configureConnectors() {
HttpConfiguration httpConfiguration = new HttpConfiguration();
// try {
if (httpPortStr != null || httpsPortStr != null) {
+ // TODO deal with hostname resolving taking too much time
+// String fallBackHostname = InetAddress.getLocalHost().getHostName();
+ String fallBackHostname = cmsState != null ? cmsState.getHostname() : "::1";
+
boolean httpEnabled = httpPortStr != null;
// props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled);
boolean httpsEnabled = httpsPortStr != null;
httpConnector.setPort(httpPort);
httpConnector.setHost(httpHost);
httpConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
+
+ httpAddress = new InetSocketAddress(httpHost != null ? httpHost : fallBackHostname, httpPort);
}
if (httpsEnabled) {
int httpsPort = Integer.parseInt(httpsPortStr);
httpsConnector.setPort(httpsPort);
httpsConnector.setHost(httpHost);
+
+ httpsAddress = new InetSocketAddress(httpHost != null ? httpHost : fallBackHostname, httpsPort);
}
}
}
protected String getDeployProperty(CmsDeployProperty deployProperty) {
- return System.getProperty(deployProperty.getProperty());
+ return cmsState != null ? cmsState.getDeployProperty(deployProperty.getProperty())
+ : System.getProperty(deployProperty.getProperty());
}
private String httpPortsMsg() {
}
-
+ public void setCmsState(CmsState cmsState) {
+ this.cmsState = cmsState;
+ }
+
public boolean isStarted() {
return started;
}
<provide interface="org.argeo.api.cms.CmsContext"/>
</service>
<reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
+ <reference bind="setCmsEventBus" cardinality="1..1" interface="org.argeo.api.cms.CmsEventBus" name="CmsEventBus" policy="static"/>
<reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
<reference bind="setUuidFactory" cardinality="1..1" interface="org.argeo.api.uuid.UuidFactory" name="UuidFactory" policy="static"/>
</scr:component>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="CMS Event Bus">
+ <implementation class="org.argeo.cms.internal.runtime.CmsEventBusImpl"/>
+ <service>
+ <provide interface="org.argeo.api.cms.CmsEventBus"/>
+ </service>
+</scr:component>
Service-Component:\
OSGI-INF/cmsOsgiLogger.xml,\
-OSGI-INF/cmsState.xml,\
OSGI-INF/uuidFactory.xml,\
+OSGI-INF/cmsEventBus.xml,\
+OSGI-INF/cmsState.xml,\
OSGI-INF/transactionManager.xml,\
OSGI-INF/cmsUserAdmin.xml,\
OSGI-INF/cmsUserManager.xml,\
bin.includes = META-INF/,\
.,\
bin/,\
- OSGI-INF/
+ OSGI-INF/,\
+ OSGI-INF/cmsEventBus.xml
source.. = src/
output.. = bin/
import org.argeo.api.cms.CmsAuth;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
-import org.argeo.cms.internal.http.CmsAuthenticator;
import org.argeo.cms.internal.runtime.CmsContextImpl;
import org.argeo.util.http.HttpHeader;
import org.ietf.jgss.GSSContext;
public static int askForWwwAuth(RemoteAuthResponse remoteAuthResponse, String realm, boolean forceBasic) {
// response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
// realm=\"" + httpAuthRealm + "\"");
- if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
+ if (hasAcceptorCredentials() && !forceBasic)// SPNEGO
remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(), HttpHeader.NEGOTIATE);
else
remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getName(),
return 401;
}
+ private static boolean hasAcceptorCredentials() {
+ return CmsContextImpl.getCmsContext().getAcceptorCredentials() != null;
+ }
+
}
import javax.security.auth.x500.X500Principal;
import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.internal.runtime.CmsContextImpl;
import org.argeo.osgi.useradmin.OsUserUtils;
import org.argeo.util.directory.ldap.IpaUtils;
import org.argeo.util.naming.LdapAttrs;
Object username = sharedState.get(CmsAuthUtils.SHARED_STATE_NAME);
if (username == null)
throw new LoginException("No username available");
- String hostname;
- try {
- hostname = InetAddress.getLocalHost().getHostName();
- } catch (UnknownHostException e) {
- log.warn("Using localhost as hostname", e);
- hostname = "localhost";
- }
+ String hostname = CmsContextImpl.getCmsContext().getCmsState().getHostname();
String baseDn = ("." + hostname).replaceAll("\\.", ",dc=");
X500Principal principal = new X500Principal(LdapAttrs.uid + "=" + username + baseDn);
authorizationName = principal.getName();
locale = Locale.getDefault();
Authorization authorization = new SingleUserAuthorization(authorizationName);
CmsAuthUtils.addAuthorization(subject, authorization);
-
- // Add standard Java OS login
+
+ // Add standard Java OS login
OsUserUtils.loginAsSystemUser(subject);
// additional principals (must be after Authorization registration)
private GSSContext checkToken(byte[] authToken) {
GSSManager manager = GSSManager.getInstance();
try {
- GSSContext gContext = manager.createContext(CmsContextImpl.getAcceptorCredentials());
+ GSSContext gContext = manager.createContext(CmsContextImpl.getCmsContext().getAcceptorCredentials());
if (gContext == null) {
log.debug("SpnegoUserRealm: failed to establish GSSContext");
}
- @Deprecated
- public static boolean hasAcceptorCredentials() {
- return CmsContextImpl.getAcceptorCredentials() != null;
- }
}
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Flow;
-import java.util.concurrent.Flow.Subscription;
-import java.util.concurrent.SubmissionPublisher;
import javax.security.auth.Subject;
import org.argeo.api.cms.CmsContext;
import org.argeo.api.cms.CmsDeployment;
-import org.argeo.api.cms.CmsEventSubscriber;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
import org.argeo.api.cms.CmsSessionId;
private CmsDeployment cmsDeployment;
private UserAdmin userAdmin;
private UuidFactory uuidFactory;
+ private CmsEventBus cmsEventBus;
// private ProvidedRepository contentRepository;
// i18n
private Map<UUID, CmsSessionImpl> cmsSessionsByUuid = new HashMap<>();
private Map<String, CmsSessionImpl> cmsSessionsByLocalId = new HashMap<>();
- // CMS events
- private Map<String, SubmissionPublisher<Map<String, Object>>> topics = new TreeMap<>();
-// private IdentityHashMap<CmsEventSubscriber, List<CmsEventFlowSubscriber>> subscriptions = new IdentityHashMap<>();
-
public void start() {
List<String> codes = CmsStateImpl.getDeployProperties(cmsState, CmsDeployProperty.LOCALE);
locales = getLocaleList(codes);
return defaultLocale;
}
+ @Override
+ public UUID timeUUID() {
+ return uuidFactory.timeUUID();
+ }
+
@Override
public List<Locale> getLocales() {
return locales;
return availableSince != null;
}
- @Override
public CmsState getCmsState() {
return cmsState;
}
+ @Override
+ public CmsEventBus getCmsEventBus() {
+ return cmsEventBus;
+ }
+
+ public void setCmsEventBus(CmsEventBus cmsEventBus) {
+ this.cmsEventBus = cmsEventBus;
+ }
+
/*
* STATIC
*/
}
/** Required by SPNEGO login module. */
- public static GSSCredential getAcceptorCredentials() {
+ public GSSCredential getAcceptorCredentials() {
// TODO find a cleaner way
- return ((CmsUserAdmin) getInstance().userAdmin).getAcceptorCredentials();
+ return ((CmsUserAdmin) userAdmin).getAcceptorCredentials();
}
private static void setInstance(CmsContextImpl cmsContextImpl) {
// instance = null;
// }
// CmsContextImpl.class.notifyAll();
-
+
if (cmsContextImpl != null) {
if (instance.isDone())
throw new IllegalStateException("CMS Context is already set");
instance.complete(cmsContextImpl);
} else {
+ if (!instance.isDone())
+ instance.cancel(true);
instance = new CompletableFuture<CmsContextImpl>();
}
}
return cmsSessionsByLocalId.get(localId);
}
- /*
- * CMS Events
- */
- public void sendEvent(String topic, Map<String, Object> event) {
- SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
- if (publisher == null)
- return; // no one is interested
- publisher.submit(event);
- }
-
- public void addEventSubscriber(String topic, CmsEventSubscriber subscriber) {
- synchronized (topics) {
- if (!topics.containsKey(topic))
- topics.put(topic, new SubmissionPublisher<>());
- }
- SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
- CmsEventFlowSubscriber flowSubscriber = new CmsEventFlowSubscriber(topic, subscriber);
- publisher.subscribe(flowSubscriber);
- }
-
- public void removeEventSubscriber(String topic, CmsEventSubscriber subscriber) {
- SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
- if (publisher == null) {
- log.error("There should be an event topic " + topic);
- return;
- }
- for (Flow.Subscriber<? super Map<String, Object>> flowSubscriber : publisher.getSubscribers()) {
- if (flowSubscriber instanceof CmsEventFlowSubscriber)
- ((CmsEventFlowSubscriber) flowSubscriber).unsubscribe();
- }
- synchronized (topics) {
- if (!publisher.hasSubscribers()) {
- publisher.close();
- topics.remove(topic);
- }
- }
- }
-
- static class CmsEventFlowSubscriber implements Flow.Subscriber<Map<String, Object>> {
- private String topic;
- private CmsEventSubscriber eventSubscriber;
-
- private Subscription subscription;
-
- public CmsEventFlowSubscriber(String topic, CmsEventSubscriber eventSubscriber) {
- this.topic = topic;
- this.eventSubscriber = eventSubscriber;
- }
-
- @Override
- public void onSubscribe(Subscription subscription) {
- this.subscription = subscription;
- subscription.request(Long.MAX_VALUE);
- }
-
- @Override
- public void onNext(Map<String, Object> item) {
- eventSubscriber.onEvent(topic, item);
-
- }
-
- @Override
- public void onError(Throwable throwable) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onComplete() {
- // TODO Auto-generated method stub
-
- }
-
- void unsubscribe() {
- if (subscription != null)
- subscription.cancel();
- else
- throw new IllegalStateException("No subscription to cancel");
- }
-
- }
-
}
--- /dev/null
+package org.argeo.cms.internal.runtime;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.Flow;
+import java.util.concurrent.Flow.Subscription;
+import java.util.concurrent.SubmissionPublisher;
+
+import org.argeo.api.cms.CmsEventBus;
+import org.argeo.api.cms.CmsEventSubscriber;
+import org.argeo.api.cms.CmsLog;
+
+public class CmsEventBusImpl implements CmsEventBus {
+ private final CmsLog log = CmsLog.getLog(CmsEventBus.class);
+
+ // CMS events
+ private Map<String, SubmissionPublisher<Map<String, Object>>> topics = new TreeMap<>();
+// private IdentityHashMap<CmsEventSubscriber, List<CmsEventFlowSubscriber>> subscriptions = new IdentityHashMap<>();
+
+ /*
+ * CMS Events
+ */
+ @Override
+ public void sendEvent(String topic, Map<String, Object> event) {
+ SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
+ if (publisher == null)
+ return; // no one is interested
+ publisher.submit(event);
+ }
+
+ @Override
+ public void addEventSubscriber(String topic, CmsEventSubscriber subscriber) {
+ synchronized (topics) {
+ if (!topics.containsKey(topic))
+ topics.put(topic, new SubmissionPublisher<>());
+ }
+ SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
+ CmsEventFlowSubscriber flowSubscriber = new CmsEventFlowSubscriber(topic, subscriber);
+ publisher.subscribe(flowSubscriber);
+ }
+
+ @Override
+ public void removeEventSubscriber(String topic, CmsEventSubscriber subscriber) {
+ SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
+ if (publisher == null) {
+ log.error("There should be an event topic " + topic);
+ return;
+ }
+ for (Flow.Subscriber<? super Map<String, Object>> flowSubscriber : publisher.getSubscribers()) {
+ if (flowSubscriber instanceof CmsEventFlowSubscriber)
+ ((CmsEventFlowSubscriber) flowSubscriber).unsubscribe();
+ }
+ synchronized (topics) {
+ if (!publisher.hasSubscribers()) {
+ publisher.close();
+ topics.remove(topic);
+ }
+ }
+ }
+
+ static class CmsEventFlowSubscriber implements Flow.Subscriber<Map<String, Object>> {
+ private String topic;
+ private CmsEventSubscriber eventSubscriber;
+
+ private Subscription subscription;
+
+ public CmsEventFlowSubscriber(String topic, CmsEventSubscriber eventSubscriber) {
+ this.topic = topic;
+ this.eventSubscriber = eventSubscriber;
+ }
+
+ @Override
+ public void onSubscribe(Subscription subscription) {
+ this.subscription = subscription;
+ subscription.request(1);
+ }
+
+ @Override
+ public void onNext(Map<String, Object> item) {
+ eventSubscriber.onEvent(topic, item);
+ subscription.request(1);
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onComplete() {
+ // TODO Auto-generated method stub
+
+ }
+
+ void unsubscribe() {
+ if (subscription != null)
+ subscription.cancel();
+ else
+ throw new IllegalStateException("No subscription to cancel");
+ }
+
+ }
+
+}
import java.io.IOException;
import java.io.Reader;
+import java.net.InetAddress;
import java.net.URL;
+import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
import java.util.StringJoiner;
import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.security.auth.login.Configuration;
private UUID uuid;
// private final boolean cleanState;
-// private String hostname;
+ private String hostname;
private UuidFactory uuidFactory;
// this.uuid = UUID.fromString(stateUuidStr);
this.uuid = uuidFactory.timeUUID();
// this.cleanState = stateUuid.equals(frameworkUuid);
-// try {
-// this.hostname = InetAddress.getLocalHost().getHostName();
-// } catch (UnknownHostException e) {
-// log.error("Cannot set hostname: " + e);
-// }
+
+ // hostname
+ this.hostname = getDeployProperty(CmsDeployProperty.HOST);
+ // TODO verify we have access to the IP address
+ if (hostname == null) {
+ final String LOCALHOST_IP = "::1";
+ ForkJoinTask<String> hostnameFJT = ForkJoinPool.commonPool().submit(() -> {
+ try {
+ String hostname = InetAddress.getLocalHost().getHostName();
+ return hostname;
+ } catch (UnknownHostException e) {
+ throw new IllegalStateException("Cannot get local hostname", e);
+ }
+ });
+ try {
+ this.hostname = hostnameFJT.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ this.hostname = LOCALHOST_IP;
+ log.warn("Could not get local hostname, using " + this.hostname);
+ }
+ }
availableSince = System.currentTimeMillis();
if (log.isDebugEnabled()) {
this.uuidFactory = uuidFactory;
}
+ public String getHostname() {
+ return hostname;
+ }
+
/**
* Called before node initialisation, in order populate OSGi instance are with
* some files (typically LDIF, etc).
--- /dev/null
+package org.argeo.cms.swt;
+
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.argeo.api.cms.CmsEventBus;
+import org.argeo.api.cms.ux.CmsImageManager;
+import org.argeo.api.cms.ux.CmsUi;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.api.cms.ux.UxContext;
+import org.argeo.cms.auth.CurrentUser;
+import org.eclipse.swt.widgets.Display;
+
+public abstract class AbstractSwtCmsView implements CmsView {
+ protected final String uiName;
+
+ protected LoginContext loginContext;
+ protected String state;
+ protected Throwable exception;
+ protected UxContext uxContext;
+ protected CmsImageManager imageManager;
+
+ protected Display display;
+ protected CmsUi ui;
+
+ protected String uid;
+
+ public AbstractSwtCmsView(String uiName) {
+ this.uiName = uiName;
+ }
+
+ public abstract CmsEventBus getCmsEventBus();
+
+ @Override
+ public void sendEvent(String topic, Map<String, Object> properties) {
+ if (properties == null)
+ properties = new HashMap<>();
+ if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid))
+ throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
+ + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
+ properties.put(CMS_VIEW_UID_PROPERTY, uid);
+ getCmsEventBus().sendEvent(topic, properties);
+ }
+
+ public <T> T doAs(PrivilegedAction<T> action) {
+ try {
+ CompletableFuture<T> result = new CompletableFuture<>();
+ Runnable toDo = () -> {
+ T res = Subject.doAs(getSubject(), action);
+ result.complete(res);
+ };
+ if (Thread.currentThread() == display.getThread())
+ toDo.run();
+ else
+ display.syncExec(toDo);
+ return result.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new IllegalStateException("Cannot execute action ins CMS view " + uid, e);
+ }
+ }
+
+ @Override
+ public UxContext getUxContext() {
+ return uxContext;
+ }
+
+ @Override
+ public String getUid() {
+ return uid;
+ }
+
+ @Override
+ public CmsImageManager<?, ?> getImageManager() {
+ return imageManager;
+ }
+
+ @Override
+ public boolean isAnonymous() {
+ return CurrentUser.isAnonymous(getSubject());
+ }
+
+ protected Subject getSubject() {
+ return loginContext.getSubject();
+ }
+
+ @Override
+ public Object getData(String key) {
+ if (ui != null) {
+ return ui.getData(key);
+ } else {
+ throw new IllegalStateException("UI is not initialized");
+ }
+ }
+
+ @Override
+ public void setData(String key, Object value) {
+ if (ui != null) {
+ ui.setData(key, value);
+ } else {
+ throw new IllegalStateException("UI is not initialized");
+ }
+ }
+
+}
loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, subject, this);
loginContext.login();
cmsView.authChange(loginContext);
- cmsContext.sendEvent("cms", Collections.singletonMap("msg", "New login"));
+ cmsContext.getCmsEventBus().sendEvent("cms", Collections.singletonMap("msg", "New login"));
return true;
} catch (LoginException e) {
if (log.isTraceEnabled())
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="CMS Web App Factory">
<implementation class="org.argeo.cms.web.osgi.CmsWebAppFactory"/>
<reference bind="addCmsApp" cardinality="0..n" interface="org.argeo.api.cms.CmsApp" name="CmsApp" policy="dynamic" unbind="removeCmsApp"/>
- <reference bind="setEventAdmin" cardinality="1..1" interface="org.osgi.service.event.EventAdmin" name="EventAdmin" policy="static"/>
+ <reference bind="setCmsEventBus" cardinality="1..1" interface="org.argeo.api.cms.CmsEventBus" name="CmsEventBus" policy="static"/>
</scr:component>
import org.argeo.api.cms.CmsApp;
import org.argeo.api.cms.CmsAppListener;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsTheme;
import org.argeo.api.cms.ux.CmsView;
import org.eclipse.swt.widgets.Display;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.event.EventAdmin;
/** An RWT web app integrating with a {@link CmsApp}. */
public class CmsWebApp implements ApplicationConfiguration, ExceptionHandler, CmsAppListener {
private BundleContext bundleContext;
private CmsApp cmsApp;
-// private String cmsAppId;
- private EventAdmin eventAdmin;
+
+ private CmsEventBus cmsEventBus;
private ServiceRegistration<ApplicationConfiguration> rwtAppReg;
String entryPointName = !uiName.equals("") ? "/" + uiName : "/";
application.addEntryPoint(entryPointName, () -> {
CmsWebEntryPoint entryPoint = new CmsWebEntryPoint(this, uiName);
- entryPoint.setEventAdmin(eventAdmin);
return entryPoint;
}, properties);
if (log.isDebugEnabled())
}
}
- public void setEventAdmin(EventAdmin eventAdmin) {
- this.eventAdmin = eventAdmin;
+ public void setCmsEventBus(CmsEventBus cmsEventBus) {
+ this.cmsEventBus = cmsEventBus;
+ }
+
+ public CmsEventBus getCmsEventBus() {
+ return cmsEventBus;
}
public void setContextName(String contextName) {
import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext;
import java.security.PrivilegedAction;
-import java.util.HashMap;
import java.util.Locale;
-import java.util.Map;
import java.util.UUID;
import javax.security.auth.Subject;
import org.argeo.api.cms.CmsApp;
import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
import org.argeo.api.cms.ux.CmsImageManager;
-import org.argeo.api.cms.ux.CmsUi;
import org.argeo.api.cms.ux.CmsView;
-import org.argeo.api.cms.ux.UxContext;
import org.argeo.cms.LocaleUtils;
import org.argeo.cms.auth.CurrentUser;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
import org.argeo.cms.servlet.ServletHttpRequest;
import org.argeo.cms.servlet.ServletHttpResponse;
+import org.argeo.cms.swt.AbstractSwtCmsView;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.SimpleSwtUxContext;
import org.argeo.cms.swt.acr.AcrSwtImageManager;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
+import org.eclipse.swt.widgets.Widget;
/** The {@link CmsView} for a {@link CmsWebApp}. */
@SuppressWarnings("restriction")
-public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationListener {
+public class CmsWebEntryPoint extends AbstractSwtCmsView implements EntryPoint, CmsView, BrowserNavigationListener {
private static final long serialVersionUID = 7733510691684570402L;
private final static CmsLog log = CmsLog.getLog(CmsWebEntryPoint.class);
- private EventAdmin eventAdmin;
-
private final CmsWebApp cmsWebApp;
- private final String uiName;
-
- private LoginContext loginContext;
- private String state;
- private Throwable exception;
- private UxContext uxContext;
- private CmsImageManager imageManager;
-
- private Display display;
- private CmsUi ui;
-
- private String uid;
// Client services
// private final JavaScriptExecutor jsExecutor;
private boolean multipleShells = false;
public CmsWebEntryPoint(CmsWebApp cmsWebApp, String uiName) {
+ super(uiName);
assert cmsWebApp != null;
assert uiName != null;
this.cmsWebApp = cmsWebApp;
- this.uiName = uiName;
uid = UUID.randomUUID().toString();
// Initial login
});
}
- protected Subject getSubject() {
- return loginContext.getSubject();
- }
-
- public <T> T doAs(PrivilegedAction<T> action) {
- return Subject.doAs(getSubject(), action);
- }
-
- @Override
- public boolean isAnonymous() {
- return CurrentUser.isAnonymous(getSubject());
- }
-
@Override
public synchronized void logout() {
if (loginContext == null)
return null;
}
- @Override
- public UxContext getUxContext() {
- return uxContext;
- }
-
- @Override
- public String getUid() {
- return uid;
- }
-
@Override
public void navigateTo(String state) {
exception = null;
}
@Override
- public void sendEvent(String topic, Map<String, Object> properties) {
- if (properties == null)
- properties = new HashMap<>();
- if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid))
- throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
- + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
- properties.put(CMS_VIEW_UID_PROPERTY, uid);
- eventAdmin.sendEvent(new Event(topic, properties));
+ public CmsEventBus getCmsEventBus() {
+ return cmsWebApp.getCmsEventBus();
}
@Override
return cmsSession;
}
- @Override
- public Object getData(String key) {
- if (ui != null) {
- return ui.getData(key);
- } else {
- throw new IllegalStateException("UI is not initialized");
- }
- }
-
- @Override
- public void setData(String key, Object value) {
- if (ui != null) {
- ui.setData(key, value);
- } else {
- throw new IllegalStateException("UI is not initialized");
- }
- }
-
/*
* EntryPoint IMPLEMENTATION
*/
}
return shell;
}
-
- public void setEventAdmin(EventAdmin eventAdmin) {
- this.eventAdmin = eventAdmin;
- }
-
}
import java.util.Map;
import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.cms.web.CmsWebApp;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
-import org.osgi.service.event.EventAdmin;
/** Publish a CmsApp as a RAP application. */
public class CmsWebAppFactory {
private BundleContext bundleContext = FrameworkUtil.getBundle(CmsWebAppFactory.class).getBundleContext();
private final static String CONTEXT_NAME = "contextName";
- private EventAdmin eventAdmin;
+ private CmsEventBus cmsEventBus;
private Map<String, CmsWebApp> registrations = Collections.synchronizedMap(new HashMap<>());
String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
if (contextName != null) {
CmsWebApp cmsWebApp = new CmsWebApp();
- cmsWebApp.setEventAdmin(eventAdmin);
+ cmsWebApp.setCmsEventBus(cmsEventBus);
cmsWebApp.setCmsApp(cmsApp);
Hashtable<String, String> serviceProperties = new Hashtable<>();
if (!contextName.equals(""))
}
}
- public void setEventAdmin(EventAdmin eventAdmin) {
- this.eventAdmin = eventAdmin;
+ public void setCmsEventBus(CmsEventBus cmsEventBus) {
+ this.cmsEventBus = cmsEventBus;
}
+
}
protected void postActivation(ComponentRegister register) {
if (ui) {
Component<? extends CmsUserApp> cmsAppC = register.find(CmsUserApp.class, null).first();
- CmsRcpDisplayFactory.openCmsApp(null, cmsAppC.get(), "data", (e) -> {
+ CmsRcpDisplayFactory.openCmsApp(cmsAppC.get(), "data", (e) -> {
// asynchronous in order to avoid deadlock in UI thread
ForkJoinPool.commonPool().execute(() -> stop());
});
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="CMS RCP Servlet Factory">
<implementation class="org.argeo.cms.ui.rcp.servlet.CmsRcpServletFactory"/>
<reference bind="addCmsApp" cardinality="0..n" interface="org.argeo.api.cms.CmsApp" name="CmsApp" policy="dynamic" unbind="removeCmsApp"/>
- <reference bind="setEventAdmin" cardinality="1..1" interface="org.osgi.service.event.EventAdmin" name="EventAdmin" policy="static"/>
- <reference bind="setHttpService" cardinality="1..1" interface="org.osgi.service.http.HttpService" name="HttpService" policy="static"/>
+ <reference bind="setHttpServer" cardinality="1..1" interface="com.sun.net.httpserver.HttpServer" name="HttpServer" policy="static"/>
</scr:component>
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivilegedAction;
-import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.argeo.api.cms.CmsApp;
import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
-import org.argeo.api.cms.ux.CmsImageManager;
import org.argeo.api.cms.ux.CmsTheme;
-import org.argeo.api.cms.ux.CmsUi;
import org.argeo.api.cms.ux.CmsView;
-import org.argeo.api.cms.ux.UxContext;
+import org.argeo.cms.swt.AbstractSwtCmsView;
import org.argeo.cms.swt.CmsSwtUtils;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
/** Runs a {@link CmsApp} as an SWT desktop application. */
@SuppressWarnings("restriction")
-public class CmsRcpApp implements CmsView {
+public class CmsRcpApp extends AbstractSwtCmsView implements CmsView {
private final static CmsLog log = CmsLog.getLog(CmsRcpApp.class);
- // private BundleContext bundleContext =
- // FrameworkUtil.getBundle(CmsRcpApp.class).getBundleContext();
-
private Shell shell;
private CmsApp cmsApp;
- // CMS View
- private String uid;
- private LoginContext loginContext;
-
- private EventAdmin eventAdmin;
-
private CSSEngine cssEngine;
- private CmsUi ui;
- // TODO make it configurable
- private String uiName = "desktop";
-
public CmsRcpApp(String uiName) {
+ super(uiName);
uid = UUID.randomUUID().toString();
- this.uiName = uiName;
}
public void initRcpApp() {
- Display display = Display.getCurrent();
+ display = Display.getCurrent();
shell = new Shell(display);
shell.setText("Argeo CMS");
Composite parent = shell;
* CMS VIEW
*/
- @Override
- public String getUid() {
- return uid;
- }
-
- @Override
- public UxContext getUxContext() {
- throw new UnsupportedOperationException();
- }
-
@Override
public void navigateTo(String state) {
throw new UnsupportedOperationException();
log.error("Unexpected exception in CMS RCP", e);
}
- @Override
- public CmsImageManager getImageManager() {
- throw new UnsupportedOperationException();
- }
-
@Override
public CmsSession getCmsSession() {
CmsSession cmsSession = cmsApp.getCmsContext().getCmsSession(getSubject());
return cmsSession;
}
- @Override
- public Object getData(String key) {
- if (ui != null) {
- return ui.getData(key);
- } else {
- throw new IllegalStateException("UI is not initialized");
- }
- }
-
- @Override
- public void setData(String key, Object value) {
- if (ui != null) {
- ui.setData(key, value);
- } else {
- throw new IllegalStateException("UI is not initialized");
- }
- }
-
@Override
public boolean isAnonymous() {
return false;
cssEngine.applyStyles(node, true);
}
- @Override
- public void sendEvent(String topic, Map<String, Object> properties) {
- if (properties == null)
- properties = new HashMap<>();
- if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid))
- throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
- + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
- properties.put(CMS_VIEW_UID_PROPERTY, uid);
- eventAdmin.sendEvent(new Event(topic, properties));
- }
-
- public <T> T doAs(PrivilegedAction<T> action) {
- return Subject.doAs(getSubject(), action);
- }
-
- protected Subject getSubject() {
- return loginContext.getSubject();
- }
-
public Shell getShell() {
return shell;
}
+ @Override
+ public CmsEventBus getCmsEventBus() {
+ return cmsApp.getCmsContext().getCmsEventBus();
+ }
+
/*
* DEPENDENCY INJECTION
*/
this.cmsApp = null;
}
- public void setEventAdmin(EventAdmin eventAdmin) {
- this.eventAdmin = eventAdmin;
- }
-
}
import org.argeo.api.cms.CmsApp;
import org.argeo.util.OS;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.service.event.EventAdmin;
import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Display;
/** Creates the SWT {@link Display} in a dedicated thread. */
public class CmsRcpDisplayFactory {
return display;
}
- public static void openCmsApp(EventAdmin eventAdmin, CmsApp cmsApp, String uiName,
- DisposeListener disposeListener) {
+ public static void openCmsApp(CmsApp cmsApp, String uiName, DisposeListener disposeListener) {
CmsRcpDisplayFactory.getDisplay().syncExec(() -> {
CmsRcpApp cmsRcpApp = new CmsRcpApp(uiName);
- cmsRcpApp.setEventAdmin(eventAdmin);
cmsRcpApp.setCmsApp(cmsApp, null);
cmsRcpApp.initRcpApp();
if (disposeListener != null)
import org.argeo.api.cms.CmsApp;
import org.argeo.cms.ui.rcp.CmsRcpDisplayFactory;
-import org.osgi.service.event.EventAdmin;
/** Open the related app when called. */
public class CmsRcpServlet extends HttpServlet {
private final static Logger logger = System.getLogger(CmsRcpServlet.class.getName());
private CmsApp cmsApp;
- private EventAdmin eventAdmin;
- public CmsRcpServlet(EventAdmin eventAdmin, CmsApp cmsApp) {
- Objects.requireNonNull(eventAdmin);
+ public CmsRcpServlet(CmsApp cmsApp) {
Objects.requireNonNull(cmsApp);
this.cmsApp = cmsApp;
- this.eventAdmin = eventAdmin;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = req.getPathInfo();
String uiName = path != null ? path.substring(path.lastIndexOf('/') + 1) : "";
- CmsRcpDisplayFactory.openCmsApp(eventAdmin, cmsApp, uiName, null);
+ CmsRcpDisplayFactory.openCmsApp(cmsApp, uiName, null);
logger.log(Level.DEBUG, "Opened RCP UI " + uiName + " of CMS App " + req.getServletPath());
}
package org.argeo.cms.ui.rcp.servlet;
+import static java.lang.System.Logger.Level.DEBUG;
+
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-import javax.servlet.Servlet;
import org.argeo.api.cms.CmsApp;
import org.argeo.cms.ui.rcp.CmsRcpDisplayFactory;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.http.HttpService;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
/** Publishes one {@link CmsRcpServlet} per {@link CmsApp}. */
public class CmsRcpServletFactory {
private final static Logger logger = System.getLogger(CmsRcpServletFactory.class.getName());
-
- private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpServletFactory.class).getBundleContext();
-
- private CompletableFuture<EventAdmin> eventAdmin = new CompletableFuture<>();
-
- private Map<String, ServiceRegistration<Servlet>> registrations = Collections.synchronizedMap(new HashMap<>());
+ private HttpServer httpServer;
+// private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpServletFactory.class).getBundleContext();
+//
+// private Map<String, ServiceRegistration<Servlet>> registrations = Collections.synchronizedMap(new HashMap<>());
public void init() {
}
public void addCmsApp(CmsApp cmsApp, Map<String, String> properties) {
- String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
+ final String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
if (contextName != null) {
- eventAdmin.thenAccept((eventAdmin) -> {
- CmsRcpServlet servlet = new CmsRcpServlet(eventAdmin, cmsApp);
- Hashtable<String, String> serviceProperties = new Hashtable<>();
- serviceProperties.put("osgi.http.whiteboard.servlet.pattern", "/" + contextName + "/*");
- ServiceRegistration<Servlet> sr = bundleContext.registerService(Servlet.class, servlet,
- serviceProperties);
- registrations.put(contextName, sr);
+ httpServer.createContext("/" + contextName, new HttpHandler() {
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ String path = exchange.getRequestURI().getPath();
+ String uiName = path != null ? path.substring(path.lastIndexOf('/') + 1) : "";
+ CmsRcpDisplayFactory.openCmsApp(cmsApp, uiName, null);
+ exchange.sendResponseHeaders(200, -1);
+ logger.log(Level.DEBUG, "Opened RCP UI " + uiName + " of CMS App /" + contextName);
+ }
});
+ logger.log(Level.DEBUG, "Registered RCP CMS APP /" + contextName);
+// CmsRcpServlet servlet = new CmsRcpServlet(cmsApp);
+// Hashtable<String, String> serviceProperties = new Hashtable<>();
+// serviceProperties.put("osgi.http.whiteboard.servlet.pattern", "/" + contextName + "/*");
+// ServiceRegistration<Servlet> sr = bundleContext.registerService(Servlet.class, servlet, serviceProperties);
+// registrations.put(contextName, sr);
}
}
public void removeCmsApp(CmsApp cmsApp, Map<String, String> properties) {
String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
if (contextName != null) {
- ServiceRegistration<Servlet> sr = registrations.get(contextName);
- sr.unregister();
+ httpServer.removeContext("/" + contextName);
+// ServiceRegistration<Servlet> sr = registrations.get(contextName);
+// sr.unregister();
}
}
- public void setEventAdmin(EventAdmin eventAdmin) {
- this.eventAdmin.complete(eventAdmin);
- }
-
- public void setHttpService(HttpService httpService, Map<String, Object> properties) {
- Integer httpPort = Integer.parseInt(properties.get("http.port").toString());
+ public void setHttpServer(HttpServer httpServer) {
+ this.httpServer = httpServer;
+ Integer httpPort = httpServer.getAddress().getPort();
String baseUrl = "http://localhost:" + httpPort + "/";
Path runFile = CmsRcpDisplayFactory.getUrlRunFile();
try {
} catch (IOException e) {
throw new RuntimeException("Cannot write run file to " + runFile, e);
}
- logger.log(Level.DEBUG, "RCP available under " + baseUrl + ", written to " + runFile);
+ logger.log(DEBUG, "RCP available under " + baseUrl + ", written to " + runFile);
}
protected boolean isPortAvailable(int port) {