argeo.osgi.start.2.node=\
org.eclipse.equinox.http.servlet,\
org.eclipse.equinox.http.jetty,\
-org.eclipse.rap.rwt.osgi
argeo.osgi.start.3.node=\
org.argeo.cms,\
argeo.osgi.start.4.node=\
+org.eclipse.rap.rwt.osgi,\
org.eclipse.gemini.blueprint.extender
argeo.osgi.start.4.cms=\
org.argeo.cms.demo
org.osgi.service.http.port=7070
+org.osgi.service.http.port.secure=7073
org.eclipse.equinox.http.jetty.log.stderr.threshold=info
org.osgi.framework.security=osgi
argeo.osgi.start.2.node=\
-org.argeo.cms
-
-argeo.osgi.start.3.http=\
org.eclipse.equinox.http.servlet,\
org.eclipse.equinox.http.jetty
+argeo.osgi.start.3.node=\
+org.argeo.cms
+
argeo.osgi.start.4.apps=\
org.eclipse.rap.rwt.osgi,\
org.eclipse.gemini.blueprint.extender
# HTTP
org.osgi.service.http.port=7070
-org.eclipse.equinox.http.jetty.log.stderr.threshold=info
+#org.eclipse.equinox.http.jetty.log.stderr.threshold=info
# HTTPS
-#org.osgi.service.http.port.secure=7073
+org.osgi.service.http.port.secure=7073
#org.eclipse.equinox.http.jetty.https.enabled=true
#org.eclipse.equinox.http.jetty.ssl.keystore=../../ssl/server.jks
+#org.eclipse.equinox.http.jetty.ssl.keystore=data/node.p12
+#org.eclipse.equinox.http.jetty.ssl.keystoretype=PKCS12
#org.eclipse.equinox.http.jetty.ssl.password=changeit
#org.eclipse.equinox.http.jetty.ssl.wantclientauth=true
#argeo.node.repo.maxVolatileIndexSize=1048576
# DON'T CHANGE BELOW
-org.eclipse.rap.workbenchAutostart=false
\ No newline at end of file
+org.eclipse.rap.workbenchAutostart=false
+org.eclipse.equinox.http.jetty.autostart=false
\ No newline at end of file
--- /dev/null
+package org.argeo.cms.auth;
+
+import javax.security.auth.login.LoginException;
+
+public class ThreadDeathLoginException extends LoginException {
+ private static final long serialVersionUID = 4359130889332276894L;
+
+ private final ThreadDeath threadDeath;
+
+ public ThreadDeathLoginException(String msg, ThreadDeath cause) {
+ this.threadDeath = cause;
+ }
+
+ public ThreadDeath getThreadDeath() {
+ return threadDeath;
+ }
+}
\ No newline at end of file
} catch (IOException e) {
throw new LoginException("Cannot handle http callback: "
+ e.getMessage());
+ } catch (ThreadDeath e) {
+ throw new ThreadDeathLoginException(
+ "Callbackhandler thread died", e);
} catch (UnsupportedCallbackException e) {
return false;
}
import static bitronix.tm.TransactionManagerServices.getTransactionManager;
import static bitronix.tm.TransactionManagerServices.getTransactionSynchronizationRegistry;
import static java.util.Locale.ENGLISH;
-import static org.apache.commons.io.FileUtils.copyDirectory;
import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp;
import static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstanceDir;
-import static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstancePath;
import static org.argeo.jcr.ArgeoJcrConstants.ALIAS_NODE;
import static org.argeo.jcr.ArgeoJcrConstants.JCR_REPOSITORY_ALIAS;
import static org.argeo.util.LocaleChoice.asLocaleList;
import static org.osgi.framework.Constants.FRAMEWORK_UUID;
import java.io.File;
+import java.io.FileFilter;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.security.PrivilegedAction;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.util.TransientFileFactory;
import org.argeo.cms.CmsException;
import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
import org.argeo.jcr.ArgeoJcrConstants;
+import org.eclipse.equinox.http.jetty.JettyConfigurator;
+import org.eclipse.equinox.http.jetty.JettyConstants;
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.useradmin.UserAdmin;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.BitronixTransactionSynchronizationRegistry;
-import bitronix.tm.Configuration;
import bitronix.tm.TransactionManagerServices;
/**
* </ul>
*/
final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
+ /*
+ * SERVICE REFERENCES
+ */
+ private ServiceReference<ConfigurationAdmin> configurationAdmin;
/*
* REGISTERED SERVICES
*/
public Kernel() {
nodeSecurity = new NodeSecurity();
+ // log.debug(bc.getDataFile(""));
+ // log.debug(bc.getDataFile("test"));
}
final void init() {
private void doInit() {
long begin = System.currentTimeMillis();
-
+ ConfigurationAdmin conf = findConfigurationAdmin();
// Use CMS bundle classloader
ClassLoader currentContextCl = Thread.currentThread()
.getContextClassLoader();
userAdmin = new NodeUserAdmin(transactionManager, repository);
// HTTP
+ initWebServer(conf);
ServiceReference<ExtendedHttpService> sr = bc
.getServiceReference(ExtendedHttpService.class);
if (sr != null)
// TODO also uncompress archives
if (initDir.exists())
try {
- copyDirectory(initDir, getOsgiInstanceDir());
+ FileUtils.copyDirectory(initDir, getOsgiInstanceDir(),
+ new FileFilter() {
+
+ @Override
+ public boolean accept(File pathname) {
+ if (pathname.getName().equals(".svn")
+ || pathname.getName().equals(".git"))
+ return false;
+ return true;
+ }
+ });
log.info("CMS initialized from " + initDir.getCanonicalPath());
} catch (IOException e) {
throw new CmsException("Cannot initialize from " + initDir, e);
}
}
+ /** Can be null */
+ private ConfigurationAdmin findConfigurationAdmin() {
+ configurationAdmin = bc.getServiceReference(ConfigurationAdmin.class);
+ if (configurationAdmin == null) {
+ return null;
+ }
+ return bc.getService(configurationAdmin);
+ }
+
private void initTransactionManager() {
- Configuration tmConf = TransactionManagerServices.getConfiguration();
+ bitronix.tm.Configuration tmConf = TransactionManagerServices
+ .getConfiguration();
tmConf.setServerId(getFrameworkProp(FRAMEWORK_UUID));
- File tmBaseDir = new File(getFrameworkProp(TRANSACTIONS_HOME,
- getOsgiInstancePath(DIR_TRANSACTIONS)));
+ // File tmBaseDir = new File(getFrameworkProp(TRANSACTIONS_HOME,
+ // getOsgiInstancePath(DIR_TRANSACTIONS)));
+ File tmBaseDir = bc.getDataFile(DIR_TRANSACTIONS);
File tmDir1 = new File(tmBaseDir, "btm1");
tmDir1.mkdirs();
tmConf.setLogPart1Filename(new File(tmDir1, tmDir1.getName() + ".tlog")
transactionSynchronizationRegistry = getTransactionSynchronizationRegistry();
}
+ private void initWebServer(ConfigurationAdmin conf) {
+ String httpPort = getFrameworkProp("org.osgi.service.http.port");
+ String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure");
+ try {
+ if (httpPort != null || httpsPort != null) {
+ Hashtable<String, Object> jettyProps = new Hashtable<String, Object>();
+ if (httpPort != null) {
+ jettyProps.put(JettyConstants.HTTP_PORT, httpPort);
+ jettyProps.put(JettyConstants.HTTP_ENABLED, true);
+ }
+ if (httpsPort != null) {
+ jettyProps.put(JettyConstants.HTTPS_PORT, httpsPort);
+ jettyProps.put(JettyConstants.HTTPS_ENABLED, true);
+ jettyProps.put(JettyConstants.SSL_KEYSTORETYPE, "PKCS12");
+ jettyProps.put(JettyConstants.SSL_KEYSTORE, nodeSecurity
+ .getHttpServerKeyStore().getCanonicalPath());
+ jettyProps.put(JettyConstants.SSL_PASSWORD, "changeit");
+ jettyProps.put(JettyConstants.SSL_WANTCLIENTAUTH, true);
+ }
+ if (conf != null) {
+ // TODO make filter more generic
+ String filter = "(" + JettyConstants.HTTP_PORT + "="
+ + httpPort + ")";
+ if (conf.listConfigurations(filter) != null)
+ return;
+ Configuration jettyConf = conf.createFactoryConfiguration(
+ JETTY_FACTORY_PID, null);
+ jettyConf.update(jettyProps);
+ } else {
+ JettyConfigurator.startServer("default", jettyProps);
+ }
+ }
+ } catch (Exception e) {
+ throw new CmsException("Cannot initialize web server on "
+ + httpPortsMsg(httpPort, httpsPort), e);
+ }
+ }
+
private void publish() {
// Listen to service publication (also ours)
bc.addServiceListener(Kernel.this);
Object httpsPort = sr.getProperty("https.port");
dataHttp = new DataHttp(httpService, repository);
if (log.isDebugEnabled())
- log.debug("HTTP " + httpPort
- + (httpsPort != null ? " - HTTPS " + httpsPort : ""));
+ log.debug(httpPortsMsg(httpPort, httpsPort));
+ }
+
+ private String httpPortsMsg(Object httpPort, Object httpsPort) {
+ return "HTTP " + httpPort
+ + (httpsPort != null ? " - HTTPS " + httpsPort : "");
}
@Override
final static String REPO_SEARCH_CACHE_SIZE = "argeo.node.repo.searchCacheSize";
final static String REPO_MAX_VOLATILE_INDEX_SIZE = "argeo.node.repo.maxVolatileIndexSize";
- final static String DIR_NODE = "node";
- final static String DIR_TRANSACTIONS = "transactions";
final static String TRANSACTIONS_HOME = "argeo.node.transactions.home";
final static String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale";
final static String[] DEFAULT_CNDS = { "/org/argeo/jcr/argeo.cnd",
"/org/argeo/cms/cms.cnd" };
+ // Directories
+ final static String DIR_NODE = "node";
+ final static String DIR_TRANSACTIONS = "transactions";
+ final static String DIR_PKI = "pki";
+ final static String DIR_PKI_PRIVATE = DIR_PKI + "/private";
+
// Security
final static String DEFAULT_SECURITY_KEY = "argeo";
final static String JAAS_CONFIG = "/org/argeo/cms/internal/kernel/jaas.cfg";
final static String PATH_WORKBENCH = "/ui";
final static String PATH_WORKBENCH_PUBLIC = PATH_WORKBENCH + "/public";
+ final static String JETTY_FACTORY_PID = "org.eclipse.equinox.http.jetty.config"; //$NON-NLS-1$
+
}
public final static int STAGING = 2;
public final static int DEV = 1;
- final static String SECURITY_PROVIDER = "BC";// Bouncy Castle
-
private final boolean firstInit;
- private final static Log log;
- static {
- log = LogFactory.getLog(NodeSecurity.class);
- // Make Bouncy Castle the default provider
- Provider provider = new BouncyCastleProvider();
- int position = Security.insertProviderAt(provider, 1);
- if (position == -1)
- log.error("Provider " + provider.getName()
- + " already installed and could not be set as default");
- Provider defaultProvider = Security.getProviders()[0];
- if (!defaultProvider.getName().equals(SECURITY_PROVIDER))
- log.error("Provider name is " + defaultProvider.getName()
- + " but it should be " + SECURITY_PROVIDER);
- }
-
private final Subject kernelSubject;
private int securityLevel = STAGING;
+ private final File keyStoreFile;
+
public NodeSecurity() {
// Configure JAAS first
URL url = getClass().getClassLoader().getResource(
KernelConstants.JAAS_CONFIG);
System.setProperty("java.security.auth.login.config",
url.toExternalForm());
+ // log.debug("JASS config: " + url.toExternalForm());
+ // disable Jetty autostart
+ // System.setProperty("org.eclipse.equinox.http.jetty.autostart",
+ // "false");
firstInit = !new File(getOsgiInstanceDir(), DIR_NODE).exists();
+ this.keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
+ "node.p12");
this.kernelSubject = logInKernel();
}
private void createKeyStoreIfNeeded() {
char[] ksPwd = "changeit".toCharArray();
char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
- File keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
- "node.p12");
if (!keyStoreFile.exists()) {
try {
keyStoreFile.getParentFile().mkdirs();
}
}
}
+
+ File getHttpServerKeyStore() {
+ return keyStoreFile;
+ }
+
+ private final static String SECURITY_PROVIDER = "BC";// Bouncy Castle
+ private final static Log log;
+ static {
+ log = LogFactory.getLog(NodeSecurity.class);
+ // Make Bouncy Castle the default provider
+ Provider provider = new BouncyCastleProvider();
+ int position = Security.insertProviderAt(provider, 1);
+ if (position == -1)
+ log.error("Provider " + provider.getName()
+ + " already installed and could not be set as default");
+ Provider defaultProvider = Security.getProviders()[0];
+ if (!defaultProvider.getName().equals(SECURITY_PROVIDER))
+ log.error("Provider name is " + defaultProvider.getName()
+ + " but it should be " + SECURITY_PROVIDER);
+ }
}
EDU.oswego.cs.dl.util.concurrent,\
org.apache.lucene,\
org.apache.tika.core,\
- org.apache.tika.parsers,\
org.apache.commons.dbcp,\
org.apache.commons.pool,\
org.argeo.server.jcr
import org.eclipse.ui.PlatformUI;
public class RapWorkbenchLogin extends WorkbenchLogin {
+ // private final static Log log =
+ // LogFactory.getLog(RapWorkbenchLogin.class);
@Override
protected int createAndRunWorkbench(Display display, String username) {
public int createUI() {
JavaScriptExecutor jsExecutor = RWT.getClient().getService(
JavaScriptExecutor.class);
- int returnCode = super.createUI();
- jsExecutor.execute("location.reload()");
+ int returnCode;
+ try {
+ returnCode = super.createUI();
+ } finally {
+ // always reload
+ jsExecutor.execute("location.reload()");
+ }
return returnCode;
}
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.CredentialNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.apache.commons.logging.LogFactory;
import org.argeo.ArgeoException;
import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.ThreadDeathLoginException;
import org.argeo.cms.widgets.auth.DefaultLoginDialog;
import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
import org.eclipse.jface.dialogs.MessageDialog;
subject = new Subject();
final LoginContext loginContext;
+ DefaultLoginDialog callbackHandler;
try {
- CallbackHandler callbackHandler = new DefaultLoginDialog(
+ callbackHandler = new DefaultLoginDialog(
display.getActiveShell());
loginContext = new LoginContext(
AuthConstants.LOGIN_CONTEXT_USER, subject,
"Bad Credentials", e.getMessage());
// retry login
continue tryLogin;
+ } catch (CredentialNotFoundException e) {
+ MessageDialog.openInformation(display.getActiveShell(),
+ "No Credentials", e.getMessage());
+ // retry login
+ continue tryLogin;
} catch (LoginException e) {
+ callbackHandler.getShell().dispose();
return processLoginDeath(display, e);
}
}
return returnCode;
}
- private Integer processLoginDeath(Display display, LoginException e) {
+ private Integer processLoginDeath(Display display, Throwable e) {
// check thread death
ThreadDeath td = wasCausedByThreadDeath(e);
if (td != null) {
protected ThreadDeath wasCausedByThreadDeath(Throwable t) {
if (t instanceof ThreadDeath)
return (ThreadDeath) t;
-
+ if (t instanceof ThreadDeathLoginException)
+ return ((ThreadDeathLoginException) t).getThreadDeath();
if (t.getCause() != null)
return wasCausedByThreadDeath(t.getCause());
else
import org.argeo.cms.auth.HttpRequestCallbackHandler;
import org.argeo.cms.widgets.auth.CmsLogin;
import org.argeo.cms.widgets.auth.CmsLoginShell;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
import org.argeo.eclipse.ui.specific.UiContext;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.application.EntryPoint;
CmsLoginShell loginShell = createCmsLoginShell();
loginShell.open();
while (!loginShell.getShell().isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
+ try {
+ if (!display.readAndDispatch())
+ display.sleep();
+ } catch (Exception e1) {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e2) {
+ // silent
+ }
+ ErrorFeedback.show("Login failed", e1);
+ return -1;
}
}
} catch (LoginException e) {
EDU.oswego.cs.dl.util.concurrent,\
org.apache.lucene,\
org.apache.tika.core,\
- org.apache.tika.parsers,\
org.apache.commons.dbcp,\
org.apache.commons.pool