From dc7449a6e40048a1657f5a09a3c005decd8184dd Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Tue, 21 Sep 2010 12:44:58 +0800 Subject: [PATCH] Implemented restlet base remote Server and Status service for swing client using ssl and http basic authentication. --- client/META-INF/MANIFEST.MF | 15 +- client/plugin.xml | 12 + .../src/org/adempiere/client/Application.java | 32 +++ .../client/ClientCredentialDialog.java | 222 +++++++++++++++++ .../client/ClientSSLContextFactory.java | 233 ++++++++++++++++++ .../org/adempiere/client/ServerInterface.java | 208 ++++++++++++++++ .../org/adempiere/client/StatusInterface.java | 191 ++++++++++++++ client/src/org/compiere/apps/AEnv.java | 2 +- client/src/org/compiere/apps/ALogin.java | 24 +- client/src/org/compiere/apps/AMenu.java | 10 +- .../org/compiere/db/CConnectionDialog.java | 47 ++-- .../compiere/install/ConfigurationData.java | 11 +- serverRoot/META-INF/MANIFEST.MF | 9 + serverRoot/WEB-INF/web.xml | 27 ++ .../adempiere/web/server/BasicVerifier.java | 83 +++++++ .../web/server/ServerApplication.java | 68 +++++ .../server/command/ExecuteProcessCommand.java | 81 ++++++ .../server/command/ExecuteTaskCommand.java | 73 ++++++ .../command/ExecuteWorkflowCommand.java | 76 ++++++ .../server/command/PostDocumentCommand.java | 74 ++++++ .../web/server/command/ResetCacheCommand.java | 69 ++++++ .../web/server/command/SendEmailCommand.java | 68 +++++ .../web/server/status/DatabaseResource.java | 53 ++++ .../web/server/status/VersionResource.java | 36 +++ .../org/compiere/web/AdempiereMonitor.java | 128 +++++++++- .../servlet/org/compiere/web/StatusInfo.java | 56 +---- .../org/compiere/apps/AbstractProcessCtl.java | 2 +- 27 files changed, 1812 insertions(+), 98 deletions(-) create mode 100644 client/src/org/adempiere/client/ClientCredentialDialog.java create mode 100644 client/src/org/adempiere/client/ClientSSLContextFactory.java create mode 100644 client/src/org/adempiere/client/ServerInterface.java create mode 100644 client/src/org/adempiere/client/StatusInterface.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/BasicVerifier.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/ServerApplication.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteProcessCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteTaskCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteWorkflowCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/PostDocumentCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/ResetCacheCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/command/SendEmailCommand.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/status/DatabaseResource.java create mode 100644 serverRoot/src/main/servlet/org/adempiere/web/server/status/VersionResource.java diff --git a/client/META-INF/MANIFEST.MF b/client/META-INF/MANIFEST.MF index 841131ba86..175cfc152f 100644 --- a/client/META-INF/MANIFEST.MF +++ b/client/META-INF/MANIFEST.MF @@ -30,6 +30,17 @@ Require-Bundle: org.adempiere.base;bundle-version="1.0.0", org.adempiere.ui.base;bundle-version="1.0.0" Eclipse-ExtensibleAPI: true Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: org.eclipse.core.runtime;version="3.4.0", +Import-Package: javax.net.ssl, + org.eclipse.core.runtime;version="3.4.0", org.eclipse.equinox.app, - org.osgi.framework;version="1.5.0" + org.osgi.framework;version="1.5.0", + org.restlet, + org.restlet.data, + org.restlet.engine, + org.restlet.engine.security, + org.restlet.ext.net, + org.restlet.representation, + org.restlet.resource, + org.restlet.security, + org.restlet.service, + org.restlet.util diff --git a/client/plugin.xml b/client/plugin.xml index 77c0ea0b4b..a444401f4c 100644 --- a/client/plugin.xml +++ b/client/plugin.xml @@ -24,5 +24,17 @@ class="org.compiere.print.SwingViewerProvider"> + + + + + + + + diff --git a/client/src/org/adempiere/client/Application.java b/client/src/org/adempiere/client/Application.java index a58e0870c3..aaeee2adf6 100644 --- a/client/src/org/adempiere/client/Application.java +++ b/client/src/org/adempiere/client/Application.java @@ -1,14 +1,46 @@ package org.adempiere.client; +import java.util.ArrayList; +import java.util.List; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSession; + import org.compiere.util.CLogger; + import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; +import org.restlet.Client; +import org.restlet.Context; +import org.restlet.data.Protocol; +import org.restlet.ext.net.HttpClientHelper; public class Application implements IApplication { private static CLogger log = CLogger.getCLogger(Application.class); + + public static Context context = null; public Object start(IApplicationContext ctx) throws Exception { log.info("Starting client"); + // A HOSTNAME VERIFIER THAT ACCEPTS EVERY HOSTS + HostnameVerifier myhostnameverifier = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + + // + //start restlet context + context = new Context(); + context.getAttributes().put("sslContextFactory", new ClientSSLContextFactory()); + context.getAttributes().put("hostnameVerifier", myhostnameverifier); + List list = new ArrayList(); + list.add(Protocol.HTTPS); + Client client = new Client(context, list, HttpClientHelper.class.getName()); + context.setClientDispatcher(client); + client.start(); + org.compiere.AdempiereClient.main(new String[]{}); return IApplication.EXIT_OK; } diff --git a/client/src/org/adempiere/client/ClientCredentialDialog.java b/client/src/org/adempiere/client/ClientCredentialDialog.java new file mode 100644 index 0000000000..f1dd0ec164 --- /dev/null +++ b/client/src/org/adempiere/client/ClientCredentialDialog.java @@ -0,0 +1,222 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.client; + +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.awt.Dialog; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.util.ResourceBundle; + +import javax.swing.JPasswordField; +import javax.swing.SwingConstants; + +import org.compiere.Adempiere; +import org.compiere.apps.ConfirmPanel; +import org.compiere.swing.CDialog; +import org.compiere.swing.CLabel; +import org.compiere.swing.CPanel; +import org.compiere.swing.CTextField; +import org.compiere.util.CLogger; +import org.compiere.util.Ini; + +/** + * + * @author hengsin + * + */ +public final class ClientCredentialDialog extends CDialog + implements ActionListener +{ + + /** + * generated serial version Id + */ + private static final long serialVersionUID = 2728290476926236505L; + + + /** + * Construct the dialog. + * Need to call initLogin for dynamic start + * @param parent parent + */ + public ClientCredentialDialog (Dialog parent) + { + super (parent, "Login", true); // Modal + log.finer(""); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + res = ResourceBundle.getBundle(RESOURCE); + // + try + { + jbInit(); + initLogin(); + } + catch(Exception e) + { + log.severe(e.toString()); + } + // Focus to OK + this.getRootPane().setDefaultButton(confirmPanel.getOKButton()); + parent.setIconImage(Adempiere.getImage16()); + } // ALogin + + + protected static final String RESOURCE = "org.compiere.apps.ALoginRes"; + private static ResourceBundle res = ResourceBundle.getBundle(RESOURCE); + /** Logger */ + private static CLogger log = CLogger.getCLogger(ClientCredentialDialog.class); + + private CPanel mainPanel = new CPanel(new BorderLayout()); + private CLabel userLabel = new CLabel(); + private CTextField userTextField = new CTextField(); + private CLabel passwordLabel = new CLabel(); + private JPasswordField passwordField = new JPasswordField(); + private GridBagLayout loginLayout = new GridBagLayout(); + private CPanel loginPanel = new CPanel(loginLayout); + private CPanel southPanel = new CPanel(); + private BorderLayout southLayout = new BorderLayout(); + private ConfirmPanel confirmPanel = new ConfirmPanel(true, false, false, false, false, false, false); + /** Combo Active */ + private boolean m_okPressed = false; + + + /************************************************************************** + * Component initialization + * @throws Exception + */ + private void jbInit() throws Exception + { + this.setName("Login"); + userLabel.setRequestFocusEnabled(false); + userLabel.setLabelFor(userTextField); + passwordLabel.setRequestFocusEnabled(false); + passwordLabel.setLabelFor(passwordField); + southPanel.setLayout(southLayout); + + userLabel.setHorizontalAlignment(SwingConstants.RIGHT); + userLabel.setText(res.getString("User")); + userLabel.setLabelFor(userTextField); + loginPanel.add(userLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0 + ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 12, 5, 5), 0, 0)); + userTextField.setText("System"); // default + loginPanel.add(userTextField, new GridBagConstraints(1, 3, 3, 1, 1.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 12), 0, 0)); + passwordLabel.setHorizontalAlignment(SwingConstants.RIGHT); + passwordLabel.setText(res.getString("Password")); + passwordLabel.setLabelFor(passwordField); + loginPanel.add(passwordLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0 + ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 12, 5, 5), 0, 0)); + passwordField.setText("System"); // default + loginPanel.add(passwordField, new GridBagConstraints(1, 4, 3, 1, 1.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 5, 12), 0, 0)); + + // + this.getContentPane().add(mainPanel); + mainPanel.add(loginPanel, BorderLayout.CENTER); + mainPanel.setName("loginMainPanel"); + mainPanel.add(southPanel, BorderLayout.SOUTH); + // + southPanel.add(confirmPanel, BorderLayout.NORTH); + confirmPanel.addActionListener(this); + } // jbInit + + /** + * Set Initial & Ini Parameters + * Optional Automatic login + * @return true, if connected & parameters set + */ + public boolean initLogin() + { + // Application/PWD + userTextField.setText(Ini.getProperty(Ini.P_UID)); + if (Ini.isPropertyBool(Ini.P_STORE_PWD)) + passwordField.setText(Ini.getProperty(Ini.P_PWD)); + else + passwordField.setText(""); + + return false; + } // initLogin + + /** + * Window Events - requestFocus + * @param e event + */ + protected void processWindowEvent(WindowEvent e) + { + super.processWindowEvent(e); + if (e.getID() == WindowEvent.WINDOW_OPENED) + { + this.toFront(); + confirmPanel.getOKButton().requestFocusInWindow(); + } + } // processWindowEvent + + /************************************************************************* + * Exit action performed + */ + private void appExit() + { + dispose(); + } // appExit_actionPerformed + + + /** + * Did the user press OK + * @return true if user pressed final OK button + */ + public boolean isOKpressed() + { + return m_okPressed; + } // isOKpressed + + /************************************************************************** + * Action Event handler + * @param e event + */ + public void actionPerformed(ActionEvent e) + { + if (e.getActionCommand().equals(ConfirmPanel.A_OK)) + { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + m_okPressed = true; + appExit(); + } + else if (e.getActionCommand().equals(ConfirmPanel.A_CANCEL)) + { + m_okPressed = false; + appExit(); + } + } // actionPerformed + + /** + * @return user id + */ + public String getUserId() + { + return userTextField.getText(); + } + + /** + * @return password + */ + public char[] getPassword() + { + return passwordField.getPassword(); + } +} diff --git a/client/src/org/adempiere/client/ClientSSLContextFactory.java b/client/src/org/adempiere/client/ClientSSLContextFactory.java new file mode 100644 index 0000000000..6fbdf2de1d --- /dev/null +++ b/client/src/org/adempiere/client/ClientSSLContextFactory.java @@ -0,0 +1,233 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.client; + +import java.io.FileInputStream; +import java.security.KeyStore; +import java.security.SecureRandom; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import org.restlet.engine.security.DefaultSslContextFactory; + +/** + * Temporary workaround to support ssl connection to server with self signed certificate. + * @author hengsin + * + */ +public class ClientSSLContextFactory extends DefaultSslContextFactory { + + /** + * Name of the KeyManager algorithm. + */ + private volatile String keyManagerAlgorithm = System.getProperty( + "ssl.KeyManagerFactory.algorithm", + KeyManagerFactory.getDefaultAlgorithm()); + + /** + * Password for the key in the keystore (as a String). + */ + private volatile char[] keyStoreKeyPassword = (System.getProperty( + "javax.net.ssl.keyPassword", + System.getProperty("javax.net.ssl.keyStorePassword")) != null) ? System + .getProperty("javax.net.ssl.keyPassword", + System.getProperty("javax.net.ssl.keyStorePassword")) + .toCharArray() : null; + + /** + * Password for the keystore (as a String). + */ + private volatile char[] keyStorePassword = (System + .getProperty("javax.net.ssl.keyStorePassword") != null) ? System + .getProperty("javax.net.ssl.keyStorePassword").toCharArray() : null; + + /** + * Path to the KeyStore file. + */ + private volatile String keyStorePath = System + .getProperty("javax.net.ssl.keyStore"); + + /** + * Name of the keystore provider. + */ + private volatile String keyStoreProvider = System + .getProperty("javax.net.ssl.keyStoreProvider"); + + /** + * KeyStore type of the keystore. + */ + private volatile String keyStoreType = System + .getProperty("javax.net.ssl.keyStoreType"); + + /** + * Name of the SecureRandom algorithm. + */ + private volatile String secureRandomAlgorithm = null; + + /** + * Name of the protocol to use when creating the SSLContext. + */ + private volatile String secureSocketProtocol = "TLS"; + /** + * Name of the TrustManager algorithm. + */ + private volatile String trustManagerAlgorithm = System.getProperty( + "ssl.TrustManagerFactory.algorithm", + TrustManagerFactory.getDefaultAlgorithm()); + + /** + * Password for the trust store keystore. + */ + private volatile char[] trustStorePassword = (System + .getProperty("javax.net.ssl.trustStorePassword") != null) ? System + .getProperty("javax.net.ssl.trustStorePassword").toCharArray() + : null; + + /** + * Path to the trust store (keystore) file. + */ + private volatile String trustStorePath = System + .getProperty("javax.net.ssl.trustStore"); + + /** + * Name of the trust store (keystore) provider. + */ + private volatile String trustStoreProvider = System + .getProperty("javax.net.ssl.trustStoreProvider"); + + /** + * KeyStore type of the trust store. + */ + private volatile String trustStoreType = System + .getProperty("javax.net.ssl.trustStoreType"); + + /** + * Creates a configured and initialised SSLContext from the values set via + * the various setters of this class. If keyStorePath, + * keyStoreProvider, keyStoreType are all + * null, the SSLContext will be initialised with a + * null array of KeyManagers. Similarly, if + * trustStorePath, trustStoreProvider, + * trustStoreType are all null, a + * null array of TrustManagers will be used. + * + * @see SSLContext#init(javax.net.ssl.KeyManager[], + * javax.net.ssl.TrustManager[], SecureRandom) + */ + @Override + public SSLContext createSslContext() throws Exception { + + KeyManagerFactory kmf = null; + if ((this.keyStorePath != null) || (this.keyStoreProvider != null) + || (this.keyStoreType != null)) { + /* + * Loads the key store. + */ + final KeyStore keyStore = (this.keyStoreProvider != null) ? KeyStore + .getInstance( + (this.keyStoreType != null) ? this.keyStoreType + : KeyStore.getDefaultType(), + this.keyStoreProvider) + : KeyStore + .getInstance((this.keyStoreType != null) ? this.keyStoreType + : KeyStore.getDefaultType()); + FileInputStream keyStoreInputStream = null; + try { + keyStoreInputStream = ((this.keyStorePath != null) && (!"NONE" + .equals(this.keyStorePath))) ? new FileInputStream( + this.keyStorePath) : null; + keyStore.load(keyStoreInputStream, this.keyStorePassword); + } finally { + if (keyStoreInputStream != null) { + keyStoreInputStream.close(); + } + } + + /* + * Creates the key-manager factory. + */ + kmf = KeyManagerFactory.getInstance(this.keyManagerAlgorithm); + kmf.init(keyStore, this.keyStoreKeyPassword); + } + + TrustManagerFactory tmf = null; + if ((this.trustStorePath != null) || (this.trustStoreProvider != null) + || (this.trustStoreType != null)) { + /* + * Loads the trust store. + */ + final KeyStore trustStore = (this.trustStoreProvider != null) ? KeyStore + .getInstance( + (this.trustStoreType != null) ? this.trustStoreType + : KeyStore.getDefaultType(), + this.trustStoreProvider) + : KeyStore + .getInstance((this.trustStoreType != null) ? this.trustStoreType + : KeyStore.getDefaultType()); + + FileInputStream trustStoreInputStream = null; + try { + trustStoreInputStream = ((this.trustStorePath != null) && (!"NONE" + .equals(this.trustStorePath))) ? new FileInputStream( + this.trustStorePath) : null; + trustStore.load(trustStoreInputStream, this.trustStorePassword); + } finally { + if (trustStoreInputStream != null) { + trustStoreInputStream.close(); + } + } + + /* + * Creates the trust-manager factory. + */ + tmf = TrustManagerFactory.getInstance(this.trustManagerAlgorithm); + tmf.init(trustStore); + } + + TrustManager[] trustManagers = null; + if (tmf != null) { + trustManagers = tmf.getTrustManagers(); + } else { + trustManagers = new TrustManager[]{ + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + } + /* + * Creates the SSLContext. + */ + final SSLContext sslContext = SSLContext + .getInstance(this.secureSocketProtocol); + SecureRandom sr = null; + if (this.secureRandomAlgorithm != null) { + sr = SecureRandom.getInstance(this.secureRandomAlgorithm); + } + sslContext.init(kmf != null ? kmf.getKeyManagers() : null, trustManagers, sr); + + return sslContext; + } + +} diff --git a/client/src/org/adempiere/client/ServerInterface.java b/client/src/org/adempiere/client/ServerInterface.java new file mode 100644 index 0000000000..8f08729345 --- /dev/null +++ b/client/src/org/adempiere/client/ServerInterface.java @@ -0,0 +1,208 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.client; + +import java.io.Serializable; +import java.net.URI; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.db.CConnection; +import org.compiere.db.SecurityPrincipal; +import org.compiere.interfaces.Server; +import org.compiere.process.ProcessInfo; +import org.compiere.util.EMail; +import org.restlet.Context; +import org.restlet.data.ChallengeResponse; +import org.restlet.data.ChallengeScheme; +import org.restlet.resource.ClientResource; +import org.restlet.representation.ObjectRepresentation; +import org.restlet.representation.Representation; + +/** + * Server interface using restlet. Use ssl and http basic authentication. + * @author hengsin + */ +public class ServerInterface implements Server { + + private ClientResource createClientResource(URI uri) { + Context context = getContext(); + ClientResource resource = new ClientResource(context, uri); + resource.setChallengeResponse(createChallengeResponse()); + return resource; + } + + private ChallengeResponse createChallengeResponse() + { + SecurityPrincipal principal = CConnection.get().getAppServerCredential(); + ChallengeResponse cr = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, principal.identity, principal.secret); + return cr; + } + + private Context getContext() { + return Application.context; + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#postImmediate(java.util.Properties, int, int, int, boolean) + */ + @Override + public String postImmediate(Properties ctx, int AD_Client_ID, + int AD_Table_ID, int Record_ID, boolean force) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("AD_Table_ID", AD_Table_ID); + map.put("Record_ID", Record_ID); + map.put("force", force); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/postDocument", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#process(java.util.Properties, org.compiere.process.ProcessInfo) + */ + @Override + public ProcessInfo process(Properties ctx, ProcessInfo pi) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("processInfo", pi); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/executeProcess", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation entity = new ObjectRepresentation(map); + Representation response = resource.post(entity); + ProcessInfo responseInfo = RestletUtil.toObject(response); + return responseInfo; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#workflow(java.util.Properties, org.compiere.process.ProcessInfo, int) + */ + @Override + public ProcessInfo workflow(Properties ctx, ProcessInfo pi, + int AD_Workflow_ID) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("AD_Workflow_ID", AD_Workflow_ID); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/executeWorkflow", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + ProcessInfo responseInfo = RestletUtil.toObject(response); + return responseInfo; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#sendEMail(java.util.Properties, org.compiere.util.EMail) + */ + @Override + public String sendEMail(Properties ctx, EMail email) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("email", email); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/sendEmail", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#executeTask(java.util.Properties, int) + */ + @Override + public String executeTask(Properties ctx, int AD_Task_ID) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("AD_Task_ID", AD_Task_ID); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/executeTask", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#cacheReset(java.util.Properties, java.lang.String, int) + */ + @Override + public int cacheReset(Properties ctx, String tableName, int Record_ID) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("tableName", tableName); + map.put("Record_ID", Record_ID); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/resetCache", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + return response != null ? Integer.parseInt(response.getText()) : 0; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + /* (non-Javadoc) + * @see org.compiere.interfaces.Server#dbProcess(java.util.Properties, org.compiere.process.ProcessInfo, java.lang.String) + */ + @Override + public ProcessInfo dbProcess(Properties ctx, ProcessInfo processInfo, + String procedureName) { + HashMap map = new HashMap(); + map.put("context", ctx); + map.put("processInfo", processInfo); + map.put("procedureName", procedureName); + + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/command/executeProcess", null, null); + ClientResource resource = createClientResource(uri); + ObjectRepresentation> entity = new ObjectRepresentation>(map); + Representation response = resource.post(entity); + ProcessInfo responseInfo = RestletUtil.toObject(response); + return responseInfo; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + +} diff --git a/client/src/org/adempiere/client/StatusInterface.java b/client/src/org/adempiere/client/StatusInterface.java new file mode 100644 index 0000000000..e2db297db1 --- /dev/null +++ b/client/src/org/adempiere/client/StatusInterface.java @@ -0,0 +1,191 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.client; + +import java.net.URI; + +import org.adempiere.exceptions.AdempiereException; +import org.compiere.db.CConnection; +import org.compiere.db.SecurityPrincipal; +import org.compiere.interfaces.Status; +import org.restlet.Context; +import org.restlet.data.ChallengeResponse; +import org.restlet.data.ChallengeScheme; +import org.restlet.representation.Representation; +import org.restlet.resource.ClientResource; + +/** + * Status interface using restlet. Use ssl and http basic authentication. + * @author hengsin + * + */ +public class StatusInterface implements Status { + + private ClientResource createClientResource(URI uri) { + Context context = getContext(); + ClientResource resource = new ClientResource(context, uri); + resource.setChallengeResponse(createChallengeResponse()); + return resource; + } + + private ChallengeResponse createChallengeResponse() + { + SecurityPrincipal principal = CConnection.get().getAppServerCredential(); + if (principal != null) + { + ChallengeResponse cr = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, principal.identity, principal.secret); + return cr; + } + else + { + return null; + } + } + + private Context getContext() { + return Application.context; + } + + @Override + public String getDateVersion() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/version/date", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + e.printStackTrace(); + throw new AdempiereException(e); + } + } + + @Override + public String getMainVersion() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/version/main", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getDbType() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/type", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getDbHost() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/host", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public int getDbPort() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/port", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return Integer.parseInt(response.getText()); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getDbName() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/name", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getConnectionURL() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/url", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getDbUid() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/uid", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getDbPwd() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/password", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public String getFwHost() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/fwhost", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return response != null ? response.getText() : ""; + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public int getFwPort() { + try { + URI uri = new URI("https", null, CConnection.get().getAppsHost(), CConnection.get().getSSLPort(), "/admin/server/status/database/fwport", null, null); + ClientResource resource = createClientResource(uri); + Representation response = resource.get(); + return Integer.parseInt(response.getText()); + } catch (Exception e) { + throw new AdempiereException(e); + } + } +} diff --git a/client/src/org/compiere/apps/AEnv.java b/client/src/org/compiere/apps/AEnv.java index 5751f15a20..1ddec839d5 100644 --- a/client/src/org/compiere/apps/AEnv.java +++ b/client/src/org/compiere/apps/AEnv.java @@ -953,7 +953,7 @@ public final class AEnv Server server = CConnection.get().getServer(); if (server != null) { - server.cacheReset(tableName, Record_ID); + server.cacheReset(Env.getRemoteCallCtx(Env.getCtx()), tableName, Record_ID); } } catch (Exception e) diff --git a/client/src/org/compiere/apps/ALogin.java b/client/src/org/compiere/apps/ALogin.java index 4608a176a8..bc986f7cc1 100644 --- a/client/src/org/compiere/apps/ALogin.java +++ b/client/src/org/compiere/apps/ALogin.java @@ -112,7 +112,6 @@ public final class ALogin extends CDialog private CPanel mainPanel = new CPanel(new BorderLayout()); private CTabbedPane loginTabPane = new CTabbedPane(); -// private BorderLayout conTabLayout = new BorderLayout(); private CPanel connectionPanel = new CPanel(); private CLabel hostLabel = new CLabel(); private CConnectionEditor hostField = new CConnectionEditor(); @@ -121,7 +120,6 @@ public final class ALogin extends CDialog private CLabel passwordLabel = new CLabel(); private JPasswordField passwordField = new JPasswordField(); private CPanel defaultPanel = new CPanel(); -// private BorderLayout defaultLayout = new BorderLayout(); private CLabel clientLabel = new CLabel(); private CLabel orgLabel = new CLabel(); private CLabel dateLabel = new CLabel(); @@ -147,17 +145,13 @@ public final class ALogin extends CDialog private BorderLayout southLayout = new BorderLayout(); private StatusBar statusBar = new StatusBar(); private ConfirmPanel confirmPanel = new ConfirmPanel(true, false, false, false, false, false, false); - //private OnlineHelp onlineHelp = new OnlineHelp(true); - //private CPanel helpPanel = new CPanel(); - // private JScrollPane helpScrollPane = new JScrollPane(); - // private BorderLayout helpLayout = new BorderLayout(); /** Server Connection */ private CConnection m_cc; /** Application User */ private String m_user; /** Application Password */ - private String m_pwd; + private char[] m_pwd = new char[0]; /** Combo Active */ private boolean m_comboActive = false; @@ -411,8 +405,11 @@ public final class ALogin extends CDialog } // processWindowEvent private void validateAppServer() { - if (!CConnection.isServerEmbedded()) - m_cc.testAppsServer(); + m_user = userTextField.getText(); + m_pwd = passwordField.getPassword(); + + m_cc.setAppServerCredential(m_user, m_pwd); + m_cc.testAppsServer(); } private void connectToDatabase() { @@ -557,7 +554,7 @@ public final class ALogin extends CDialog if (loginTabPane.getSelectedIndex() == 2) // allow access to help return; - if (!(String.valueOf(passwordField.getPassword()).equals(m_pwd) + if (!(String.valueOf(passwordField.getPassword()).equals(String.valueOf(m_pwd)) && userTextField.getText().equals(m_user))) m_connectionOK = false; // @@ -623,7 +620,7 @@ public final class ALogin extends CDialog private boolean tryConnection() { m_user = userTextField.getText(); - m_pwd = new String (passwordField.getPassword()); + m_pwd = passwordField.getPassword(); // Establish connection if (!DB.isConnected(false)) @@ -647,7 +644,7 @@ public final class ALogin extends CDialog KeyNamePair[] roles = null; try { - roles = m_login.getRoles(m_user, m_pwd); + roles = m_login.getRoles(m_user, new String(m_pwd)); if (roles == null || roles.length == 0) { statusBar.setStatusLine(txt_UserPwdError, true); @@ -945,7 +942,8 @@ public final class ALogin extends CDialog txt_LoggedIn = res.getString("Authorized"); // loginTabPane.setTitleAt(0, res.getString("Connection")); - loginTabPane.setTitleAt(1, res.getString("Defaults")); + if (loginTabPane.getTabCount() > 1) + loginTabPane.setTitleAt(1, res.getString("Defaults")); confirmPanel.getOKButton().setToolTipText(res.getString("Ok")); confirmPanel.getCancelButton().setToolTipText(res.getString("Cancel")); diff --git a/client/src/org/compiere/apps/AMenu.java b/client/src/org/compiere/apps/AMenu.java index d567680c67..e46366bc39 100644 --- a/client/src/org/compiere/apps/AMenu.java +++ b/client/src/org/compiere/apps/AMenu.java @@ -37,6 +37,7 @@ import java.beans.PropertyChangeListener; import java.math.BigDecimal; import java.text.MessageFormat; import java.util.Properties; +import java.util.UUID; import java.util.logging.Level; import javax.swing.BorderFactory; @@ -55,6 +56,7 @@ import org.adempiere.plaf.AdempierePLAF; import org.compiere.Adempiere; import org.compiere.apps.wf.WFActivity; import org.compiere.apps.wf.WFPanel; +import org.compiere.db.CConnection; import org.compiere.grid.tree.VTreePanel; import org.compiere.model.MRole; import org.compiere.model.MSession; @@ -62,8 +64,6 @@ import org.compiere.model.MSysConfig; import org.compiere.model.MSystem; import org.compiere.model.MTreeNode; import org.compiere.model.MUser; -import org.compiere.print.ReportCtl; -import org.compiere.print.SwingViewerProvider; import org.compiere.swing.CButton; import org.compiere.swing.CFrame; import org.compiere.swing.CPanel; @@ -122,7 +122,11 @@ public final class AMenu extends CFrame // if (!Adempiere.startupEnvironment(true)) // Load Environment System.exit(1); - MSession.get (Env.getCtx(), true); // Start Session + MSession session = MSession.get (Env.getCtx(), true); // Start Session + session.setWebSession(UUID.randomUUID().toString()); + session.setDescription(session.getDescription() + " " + "Swing Client"); + session.saveEx(); + CConnection.get().setAppServerCredential("AD_Session_ID#"+session.getAD_Session_ID(), session.getWebSession().toCharArray()); // Setting close operation/listener - teo_sarca [ 1684168 ] setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); diff --git a/client/src/org/compiere/db/CConnectionDialog.java b/client/src/org/compiere/db/CConnectionDialog.java index ff24bdee8a..4e41b2fe59 100644 --- a/client/src/org/compiere/db/CConnectionDialog.java +++ b/client/src/org/compiere/db/CConnectionDialog.java @@ -33,7 +33,9 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPasswordField; +import org.adempiere.client.ClientCredentialDialog; import org.adempiere.plaf.AdempierePLAF; +import org.compiere.apps.AEnv; import org.compiere.swing.CButton; import org.compiere.swing.CCheckBox; import org.compiere.swing.CComboBox; @@ -43,7 +45,6 @@ import org.compiere.swing.CPanel; import org.compiere.swing.CTextField; import org.compiere.util.CLogger; import org.compiere.util.Ini; -import org.compiere.util.ValueNamePair; /** * Connection Dialog. @@ -89,18 +90,10 @@ public class CConnectionDialog extends CDialog implements ActionListener /** Resources */ private static ResourceBundle res = ResourceBundle.getBundle("org.compiere.db.DBRes"); - static - { - /** Connection Profiles */ - CConnection.CONNECTIONProfiles = new ValueNamePair[]{ - new ValueNamePair("L", res.getString("LAN")), - new ValueNamePair("V", res.getString("VPN")), - new ValueNamePair("W", res.getString("WAN")) - }; - } - /** Default HTTP Port */ public static final String APPS_PORT_HTTP = "80"; + /** Default SSL Port */ + public static final String APPS_PORT_SSL = "443"; /** Connection */ private CConnection m_cc = null; private CConnection m_ccResult = null; @@ -136,6 +129,8 @@ public class CConnectionDialog extends CDialog implements ActionListener private CCheckBox cbBequeath = new CCheckBox(); private CLabel appsHostLabel = new CLabel(); private CTextField appsHostField = new CTextField(); + private CLabel sslPortLabel = new CLabel(); + private CTextField sslPortField = new CTextField(); private CButton bTestApps = new CButton(); //private CCheckBox cbOverwrite = new CCheckBox(); private CLabel dbUidLabel = new CLabel(); @@ -176,6 +171,8 @@ public class CConnectionDialog extends CDialog implements ActionListener cbBequeath.setText(res.getString("BequeathConnection")); appsHostLabel.setText(res.getString("AppsHost")); appsHostField.setColumns(30); + sslPortLabel.setText(res.getString("AppsPort")); + sslPortField.setColumns(10); bTestApps.setText(res.getString("TestApps")); bTestApps.setHorizontalAlignment(JLabel.LEFT); //cbOverwrite.setText(res.getString("Overwrite")); @@ -195,7 +192,10 @@ public class CConnectionDialog extends CDialog implements ActionListener ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 12, 5, 5), 0, 0)); centerPanel.add(appsHostField, new GridBagConstraints(1, 1, 2, 1, 0.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 12), 0, 0)); - + centerPanel.add(sslPortLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0 + ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 12, 5, 5), 0, 0)); + centerPanel.add(sslPortField, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // centerPanel.add(bTestApps, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0 ,GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 12, 0), 0, 0)); @@ -241,7 +241,7 @@ public class CConnectionDialog extends CDialog implements ActionListener // nameField.addActionListener(this); appsHostField.addActionListener(this); - //cbOverwrite.addActionListener(this); + sslPortField.addActionListener(this); bTestApps.addActionListener(this); // dbTypeField.addActionListener(this); @@ -261,6 +261,8 @@ public class CConnectionDialog extends CDialog implements ActionListener { appsHostLabel.setVisible(false); appsHostField.setVisible(false); + sslPortLabel.setVisible(false); + sslPortField.setVisible(false); bTestApps.setVisible(false); } else // Client @@ -352,7 +354,16 @@ public class CConnectionDialog extends CDialog implements ActionListener updateCConnection(); // if (src == bTestApps) - cmd_testApps(); + { + ClientCredentialDialog ccd = new ClientCredentialDialog(this); + ccd.setModal(true); + AEnv.showCenterWindow(this, ccd); + if (ccd.isOKpressed()) + { + m_cc.setAppServerCredential(ccd.getUserId(), ccd.getPassword()); + cmd_testApps(); + } + } // Database Selection Changed else if (src == dbTypeField) @@ -379,6 +390,9 @@ public class CConnectionDialog extends CDialog implements ActionListener //hengsin: avoid unnecessary requery of application server status if (!appsHostField.getText().equals(m_cc.getAppsHost())) m_cc.setAppsHost(appsHostField.getText()); + if (!sslPortField.getText().equals(Integer.toString(m_cc.getSSLPort()))) + m_cc.setSSLPort(sslPortField.getText()); + } else m_cc.setAppsHost("localhost"); @@ -403,12 +417,13 @@ public class CConnectionDialog extends CDialog implements ActionListener m_updating = true; nameField.setText(m_cc.getName()); appsHostField.setText(m_cc.getAppsHost()); + sslPortField.setText(String.valueOf(m_cc.getSSLPort())); // bTestApps.setIcon(getStatusIcon(m_cc.isAppsServerOK(false))); // bTestApps.setToolTipText(m_cc.getRmiUri()); //cbOverwrite.setVisible(m_cc.isAppsServerOK(false)); - boolean rw = CConnection.isServerEmbedded() ? true : !m_cc.isAppsServerOK(false); + boolean rw = !m_cc.isAppsServerOK(false); // dbTypeLabel.setReadWrite(rw); dbTypeField.setReadWrite(rw); @@ -485,6 +500,8 @@ public class CConnectionDialog extends CDialog implements ActionListener private void cmd_testApps() { setBusy (true); + m_cc.setAppsHost(appsHostField.getText()); + m_cc.setSSLPort(sslPortField.getText()); Exception e = m_cc.testAppsServer(); if (e != null) { diff --git a/install/src/org/compiere/install/ConfigurationData.java b/install/src/org/compiere/install/ConfigurationData.java index b8b210562a..51133bd619 100644 --- a/install/src/org/compiere/install/ConfigurationData.java +++ b/install/src/org/compiere/install/ConfigurationData.java @@ -759,8 +759,6 @@ public class ConfigurationData log.warning("Open Socket " + host + ":" + port + " - " + pingSocket); log.fine(host + ":" + port + " - " + pingSocket); - if (pingSocket == null) - return false; // success try { @@ -848,18 +846,14 @@ public class ConfigurationData getDatabaseServer(), getDatabasePort(), getDatabaseName(), getDatabaseUser(), getDatabasePassword()); cc.setAppsHost(getAppsServer()); - cc.setConnectionProfile(CConnection.PROFILE_LAN); + cc.setWebPort(getAppsServerWebPort()); + cc.setSSLPort(getAppsServerSSLPort()); } catch(Exception e) { log.log(Level.SEVERE, "connection", e); return false; } - if (cc == null) - { - log.warning("No Connection"); - return false; - } Ini.setProperty(Ini.P_CONNECTION, cc.toStringLong()); Ini.saveProperties(false); return true; @@ -1339,6 +1333,7 @@ public class ConfigurationData else updateProperty(ADEMPIERE_DB_PASSWORD, databasePassword); } + /** * @return Returns the databasePort. */ diff --git a/serverRoot/META-INF/MANIFEST.MF b/serverRoot/META-INF/MANIFEST.MF index c0cafd46ac..0819a36fe3 100644 --- a/serverRoot/META-INF/MANIFEST.MF +++ b/serverRoot/META-INF/MANIFEST.MF @@ -15,3 +15,12 @@ Eclipse-RegisterBuddy: org.adempiere.tools Bundle-ClassPath: WEB-INF/lib/jardiff.jar, WEB-INF/lib/jnlp-servlet.jar, . +Import-Package: org.restlet, + org.restlet.data, + org.restlet.ext.servlet, + org.restlet.representation, + org.restlet.resource, + org.restlet.routing, + org.restlet.security, + org.restlet.service, + org.restlet.util diff --git a/serverRoot/WEB-INF/web.xml b/serverRoot/WEB-INF/web.xml index 301baa1e4c..1442c4cb53 100644 --- a/serverRoot/WEB-INF/web.xml +++ b/serverRoot/WEB-INF/web.xml @@ -42,6 +42,16 @@ org.compiere.web.AdempiereMonitor 1 + + + RestletServlet + org.restlet.ext.servlet.ServerServlet + + + org.restlet.application + org.adempiere.web.server.ServerApplication + + JnlpDownloadServlet *.jnlp @@ -54,6 +64,10 @@ AdempiereMonitor /adempiereMonitor/* + + RestletServlet + /server/* + 15 @@ -69,6 +83,19 @@ jnlp application/x-java-jnlp-file + + + admin + /adempiereMonitor/* + + + service + /server/* + + + CONFIDENTIAL + + adempiere.html diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/BasicVerifier.java b/serverRoot/src/main/servlet/org/adempiere/web/server/BasicVerifier.java new file mode 100644 index 0000000000..9be478bd57 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/BasicVerifier.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server; + +import java.util.Properties; +import java.util.logging.Level; + +import org.compiere.model.MSession; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.compiere.util.KeyNamePair; +import org.compiere.util.Login; +import org.restlet.security.SecretVerifier; + +/** + * Http basic authentication implementation. Support authentication using session token or + * userid+password + * @author hengsin + */ +public class BasicVerifier extends SecretVerifier { + + private final static CLogger log = CLogger.getCLogger(BasicVerifier.class); + + /* (non-Javadoc) + * @see org.restlet.security.SecretVerifier#verify(java.lang.String, char[]) + */ + @Override + public boolean verify(String identity, char[] password) + throws IllegalArgumentException { + //authenticate with session token + if (identity.startsWith("AD_Session_ID#")) + { + String sessionId = identity.substring("AD_Session_ID#".length()); + int AD_Session_ID = 0; + try + { + AD_Session_ID = Integer.parseInt(sessionId); + } + catch (Exception e) + { + log.log(Level.WARNING, "Invalid session token: " + identity); + return false; + } + MSession session = new MSession(Env.getCtx(), AD_Session_ID, null); + if (session.getAD_Session_ID() != AD_Session_ID) + { + log.log(Level.WARNING, "Session not exists in database: " + identity); + return false; + } + if (session.isProcessed()) + { + log.log(Level.WARNING, "Session have logout: " + identity); + return false; + } + if (!session.isActive()) + { + log.log(Level.WARNING, "Session isActive=false: " + identity); + return false; + } + if (!session.getWebSession().equals(new String(password))) + { + log.log(Level.WARNING, "Session token doesn't match. identity=" + identity + ", token="+new String(password)); + } + return true; + } + + //authenticate with userid+password + Login login = new Login(new Properties()); + KeyNamePair[] roles = login.getRoles(identity, new String(password)); + return (roles != null && roles.length > 0); + } + +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/ServerApplication.java b/serverRoot/src/main/servlet/org/adempiere/web/server/ServerApplication.java new file mode 100644 index 0000000000..d1906c99c3 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/ServerApplication.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server; + +import org.adempiere.web.server.command.ExecuteProcessCommand; +import org.adempiere.web.server.command.ExecuteTaskCommand; +import org.adempiere.web.server.command.ExecuteWorkflowCommand; +import org.adempiere.web.server.command.PostDocumentCommand; +import org.adempiere.web.server.command.ResetCacheCommand; +import org.adempiere.web.server.command.SendEmailCommand; +import org.adempiere.web.server.status.DatabaseResource; +import org.adempiere.web.server.status.VersionResource; +import org.restlet.Application; +import org.restlet.Restlet; +import org.restlet.data.ChallengeScheme; +import org.restlet.routing.Router; +import org.restlet.security.ChallengeAuthenticator; + +/** + * Restlet application for /command and /status service. + * @author hengsin + */ +public class ServerApplication extends Application { + + /** + * Creates a root Restlet that will receive all incoming calls. + */ + @Override + public synchronized Restlet createInboundRoot() { + // Create a router Restlet that routes each call to a new instance of HelloWorldResource. + Router router = new Router(getContext()); + + // Defines command route + // The command handler discovery can be refactor to use equinox extension in future to make this + // extensible + router.attach("/command/postDocument", PostDocumentCommand.class); + router.attach("/command/executeProcess", ExecuteProcessCommand.class); + router.attach("/command/executeWorkflow", ExecuteWorkflowCommand.class); + router.attach("/command/executeTask", ExecuteTaskCommand.class); + router.attach("/command/sendEmail", SendEmailCommand.class); + router.attach("/command/resetCache", ResetCacheCommand.class); + + // Defines config route + router.attach("/status/version/{type}", VersionResource.class); + router.attach("/status/database/{property}", DatabaseResource.class); + + + // Authenticate the whole hierarchy of URIs + ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(), + ChallengeScheme.HTTP_BASIC, "adempiere realm"); + guard.setVerifier(new BasicVerifier()); + guard.setOptional(false); + + guard.setNext(router); + + return guard; + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteProcessCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteProcessCommand.java new file mode 100644 index 0000000000..b9c7df3f6c --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteProcessCommand.java @@ -0,0 +1,81 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.model.MRole; +import org.compiere.process.ProcessInfo; +import org.compiere.util.Env; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; +import org.restlet.representation.ObjectRepresentation; +import org.restlet.representation.Representation; + +/** + * Command to execute java or db process ( AD_Process ) + * @author hengsin + * + */ +public class ExecuteProcessCommand extends ServerResource { + + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + return new ObjectRepresentation(accept(map)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private ProcessInfo accept(HashMap entity) { + Properties context = (Properties) entity.get("context"); + ProcessInfo pi = (ProcessInfo) entity.get("processInfo"); + String procedureName = (String) entity.get("procedureName"); + + MRole role = MRole.get(context, Env.getAD_Role_ID(context), Env.getAD_User_ID(context), false); + if (!role.getProcessAccess(pi.getAD_Process_ID())) { + throw new AdempiereException("Access denied."); + } + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + if (procedureName != null && procedureName.trim().length() > 0) + return bean.dbProcess(context, pi, procedureName); + else + return bean.process(context, pi); + } + finally + { + Env.setCtx(backup); + } + } + +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteTaskCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteTaskCommand.java new file mode 100644 index 0000000000..be39be01de --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteTaskCommand.java @@ -0,0 +1,73 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.model.MRole; +import org.compiere.util.Env; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +/** + * Command to execute task ( AD_Task ) + * @author hengsin + */ +public class ExecuteTaskCommand extends ServerResource { + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + return new StringRepresentation(accept(map)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private String accept(HashMap entity) { + Properties context = (Properties) entity.get("context"); + int AD_Task_ID = (Integer) entity.get("AD_Task_ID"); + + MRole role = MRole.get(context, Env.getAD_Role_ID(context), Env.getAD_User_ID(context), false); + if (!role.getTaskAccess(AD_Task_ID)) { + throw new AdempiereException("Access denied."); + } + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + return bean.executeTask(context, AD_Task_ID); + } + finally + { + Env.setCtx(backup); + } + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteWorkflowCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteWorkflowCommand.java new file mode 100644 index 0000000000..bc7eb9148a --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ExecuteWorkflowCommand.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.model.MRole; +import org.compiere.process.ProcessInfo; +import org.compiere.util.Env; +import org.restlet.representation.ObjectRepresentation; +import org.restlet.representation.Representation; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +/** + * Command to execute workflow ( AD_Workflow ) + * @author hengsin + */ +public class ExecuteWorkflowCommand extends ServerResource { + + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + return new ObjectRepresentation(accept(map)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private ProcessInfo accept(HashMap entity) { + Properties context = (Properties) entity.get("context"); + ProcessInfo pi = (ProcessInfo) entity.get("processInfo"); + + int AD_Workflow_ID = (Integer) entity.get("AD_Workflow_ID"); + MRole role = MRole.get(context, Env.getAD_Role_ID(context), Env.getAD_User_ID(context), false); + if (!role.getWorkflowAccess(AD_Workflow_ID)) { + throw new AdempiereException("Access denied."); + } + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + return bean.workflow(context, pi, AD_Workflow_ID); + } + finally + { + Env.setCtx(backup); + } + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/PostDocumentCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/PostDocumentCommand.java new file mode 100644 index 0000000000..eb4bb68315 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/PostDocumentCommand.java @@ -0,0 +1,74 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.util.Env; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +/** + * Command to post accounting document. + * @author hengsin + */ +public class PostDocumentCommand extends ServerResource { + + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + return new StringRepresentation(accept(map)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private String accept(HashMap entity) { + String msg = null; + + Properties context = (Properties) entity.get("context"); + int AD_Client_ID = Env.getAD_Client_ID(context); + int AD_Table_ID = (Integer) entity.get("AD_Table_ID"); + int Record_ID = (Integer) entity.get("Record_ID"); + boolean force = (Boolean) entity.get("force"); + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + msg = bean.postImmediate(context, AD_Client_ID, AD_Table_ID, Record_ID, force); + } + finally + { + Env.setCtx(backup); + } + return msg; + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/ResetCacheCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ResetCacheCommand.java new file mode 100644 index 0000000000..9b445a5c31 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/ResetCacheCommand.java @@ -0,0 +1,69 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.util.Env; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +/** + * Command to reset cache at server. + * @author hengsin + */ +public class ResetCacheCommand extends ServerResource { + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + int i = accept(map); + return new StringRepresentation(Integer.toString(i)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private int accept(HashMap entity) { + Properties context = (Properties) entity.get("context"); + int Record_ID = (Integer) entity.get("Record_ID"); + String tableName = (String) entity.get("tableName"); + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + return bean.cacheReset(context, tableName, Record_ID); + } + finally + { + Env.setCtx(backup); + } + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/command/SendEmailCommand.java b/serverRoot/src/main/servlet/org/adempiere/web/server/command/SendEmailCommand.java new file mode 100644 index 0000000000..bcec437bb5 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/command/SendEmailCommand.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.command; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.util.RestletUtil; +import org.compiere.interfaces.impl.ServerBean; +import org.compiere.util.EMail; +import org.compiere.util.Env; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +/** + * Command to send email from server. + * @author hengsin + */ +public class SendEmailCommand extends ServerResource { + @Override + protected Representation post(Representation entity) + throws ResourceException { + try { + HashMap map = RestletUtil.toObject(entity); + return new StringRepresentation(accept(map)); + } catch (Exception e) { + throw new AdempiereException(e); + } + } + + @Override + public boolean isNegotiated() { + return false; + } + + private String accept(HashMap entity) { + Properties context = (Properties) entity.get("context"); + EMail email = (EMail) entity.get("email"); + + ServerBean bean = new ServerBean(); + //back up properties + Properties backup = new Properties(); + backup.putAll(Env.getCtx()); + try + { + Env.setCtx(context); + return bean.sendEMail(context, email); + } + finally + { + Env.setCtx(backup); + } + } +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/status/DatabaseResource.java b/serverRoot/src/main/servlet/org/adempiere/web/server/status/DatabaseResource.java new file mode 100644 index 0000000000..b97b14fd35 --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/status/DatabaseResource.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.status; + +import org.compiere.interfaces.impl.StatusBean; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +/** + * Implement support for remote database connection property query. + * @author hengsin + * + */ +public class DatabaseResource extends ServerResource { + + @Get + public String represent() { + StatusBean status = new StatusBean(); + String property = (String) getRequestAttributes().get("property"); + String value = ""; + if ("type".equalsIgnoreCase(property)) + value = status.getDbType(); + else if ("host".equals(property)) + value = status.getDbHost(); + else if ("port".equals(property)) + value = Integer.toString(status.getDbPort()); + else if ("name".equals(property)) + value = status.getDbName(); + else if ("url".equals(property)) + value = status.getConnectionURL(); + else if ("uid".equals(property)) + value = status.getDbUid(); + else if ("password".equals(property)) + value = status.getDbPwd(); + else if ("fwhost".equals(property)) + value = status.getFwHost(); + else if ("fwport".equals(property)) + value = Integer.toString(status.getFwPort()); + + return value != null ? value : ""; + } + +} diff --git a/serverRoot/src/main/servlet/org/adempiere/web/server/status/VersionResource.java b/serverRoot/src/main/servlet/org/adempiere/web/server/status/VersionResource.java new file mode 100644 index 0000000000..10701a555d --- /dev/null +++ b/serverRoot/src/main/servlet/org/adempiere/web/server/status/VersionResource.java @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (C) 2010 Low Heng Sin All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.web.server.status; + +import org.compiere.interfaces.impl.StatusBean; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +/** + * Implement remote version property query support. + * @author hengsin + * + */ +public class VersionResource extends ServerResource { + + @Get + public String represent() { + String type = (String) getRequestAttributes().get("type"); + if ("date".equalsIgnoreCase(type)) + return new StatusBean().getDateVersion(); + else if ("main".equalsIgnoreCase(type)) + return new StatusBean().getMainVersion(); + else + return ""; + } +} diff --git a/serverRoot/src/main/servlet/org/compiere/web/AdempiereMonitor.java b/serverRoot/src/main/servlet/org/compiere/web/AdempiereMonitor.java index b04f2d93dc..fde0c7cbbf 100644 --- a/serverRoot/src/main/servlet/org/compiere/web/AdempiereMonitor.java +++ b/serverRoot/src/main/servlet/org/compiere/web/AdempiereMonitor.java @@ -19,6 +19,7 @@ package org.compiere.web; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.PrintWriter; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.RuntimeMXBean; @@ -105,21 +106,45 @@ public class AdempiereMonitor extends HttpServlet protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + boolean xmlOutput = false; + String responseType = request.getParameter("responseContentType"); + xmlOutput = "xml".equalsIgnoreCase(responseType); + m_message = null; if (processLogParameter (request, response)) + { + if (xmlOutput) + createXMLSummaryPage(request, response); return; + } if (processTraceParameter (request, response)) + { + if (xmlOutput) + createXMLSummaryPage(request, response); return; + } if (processEMailParameter (request, response)) + { + if (xmlOutput) + createXMLSummaryPage(request, response); return; + } if (processCacheParameter (request, response)) + { + if (xmlOutput) + createXMLSummaryPage(request, response); return; + } // if (processRunNowParameter (request)) ; else processActionParameter (request); - createSummaryPage(request, response); + + if (xmlOutput) + createXMLSummaryPage(request, response); + else + createSummaryPage(request, response); } // doGet /** @@ -669,6 +694,107 @@ public class AdempiereMonitor extends HttpServlet WebUtil.createResponse (request, response, this, null, doc, false); } // createSummaryPage + /************************************************************************** + * Create & Return Summary Page + * @param request request + * @param response response + * @throws ServletException + * @throws IOException + */ + private void createXMLSummaryPage (HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + response.setContentType("text/xml"); + PrintWriter writer = response.getWriter(); + + writer.println(""); + + // message + writer.println("\t"); + if (m_message != null) + { + writer.println(m_message); + } + writer.println("\t"); + + // Summary + writer.print("\t"); + writer.print(Adempiere.getName()); + writer.println(""); + + writer.print("\t"); + writer.print(Adempiere.getVersion()); + writer.println(""); + + writer.print("\t"); + writer.print(Adempiere.getImplementationVendor()); + writer.println(""); + + writer.print("\t"); + writer.print(Adempiere.getImplementationVersion()); + writer.println(""); + + writer.println("\t"); + writer.print("\t\t"); + writer.print(m_serverMgr.getDescription()); + writer.println(""); + writer.print("\t\t"); + writer.print(m_serverMgr.getStartTime()); + writer.println(""); + writer.print("\t\t"); + writer.print(m_serverMgr.getServerCount()); + writer.println(""); + + AdempiereServer[] servers = m_serverMgr.getAll(); + for (int i = 0; i < servers.length; i++) + { + AdempiereServer server = servers[i]; + writer.println("\t\t"); + writer.print("\t\t\t"); + writer.print(server.getServerID()); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getName()); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getDescription()); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getServerInfo()); + writer.println(""); + writer.print("\t\t\t"); + if (server.isAlive()) + { + if (server.isInterrupted()) + writer.print("Interrupted"); + else if (server.isSleeping()) + writer.print("Sleeping"); + else + writer.print("Running"); + } + else + writer.print("Stopped"); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getStartTime()); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getDateLastRun()); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getDateNextRun(false)); + writer.println(""); + writer.print("\t\t\t"); + writer.print(server.getStatistics()); + writer.println(""); + writer.println("\t\t"); + } + + writer.println("\t"); + + writer.flush(); + } // createSummaryPage + /** * Add Log Management to page * @param bb body diff --git a/serverRoot/src/main/servlet/org/compiere/web/StatusInfo.java b/serverRoot/src/main/servlet/org/compiere/web/StatusInfo.java index 54f1e54d92..d0cc368b40 100644 --- a/serverRoot/src/main/servlet/org/compiere/web/StatusInfo.java +++ b/serverRoot/src/main/servlet/org/compiere/web/StatusInfo.java @@ -21,16 +21,12 @@ import java.io.PrintWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; -import javax.naming.InitialContext; -import javax.naming.NamingEnumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.sql.DataSource; -import org.compiere.interfaces.Server; -import org.compiere.interfaces.Status; +import org.compiere.db.CConnection; /** * Status Info Servlet @@ -69,58 +65,10 @@ public class StatusInfo extends HttpServlet out.println("Status Info"); out.println(""); - InitialContext context = null; try { - context = new InitialContext(); - } - catch (Exception ex) - { - out.println("

" + ex + "

"); - } - - try - { - Status status = (Status)context.lookup (Status.JNDI_NAME); - out.println("

" + status.getStatus() + "

"); - } - catch (Exception ex) - { - out.println("

" + ex + "

"); - } - - try - { - Server server = (Server)context.lookup (Server.JNDI_NAME); - out.println("

" + server.getStatus() + "

"); - } - catch (Exception ex) - { - out.println("

" + ex + "

"); - } - - try - { - out.println("

-- /

"); - NamingEnumeration ne = context.list("/"); - while (ne.hasMore()) - out.println("
" + ne.nextElement()); - out.println("

-- java

"); - ne = context.list("java:"); - while (ne.hasMore()) - out.println("
" + ne.nextElement()); - out.println("

-- ejb

"); - ne = context.list("ejb"); - while (ne.hasMore()) - out.println("
" + ne.nextElement()); - // - - out.println("

-- DS

"); - DataSource ds = (DataSource)context.lookup("java:/OracleDS"); - out.println("
DataSource " + ds.getClass().getName() + " LoginTimeout=" + ds.getLoginTimeout()); - - Connection con = ds.getConnection("adempiere","adempiere"); + Connection con = CConnection.get().getConnection(true, Connection.TRANSACTION_READ_COMMITTED); out.println("
Connection "); getServletContext().log("Connection closed=" + con.isClosed()); diff --git a/uibase/src/org/compiere/apps/AbstractProcessCtl.java b/uibase/src/org/compiere/apps/AbstractProcessCtl.java index 8abc542051..f9ec2a9d98 100644 --- a/uibase/src/org/compiere/apps/AbstractProcessCtl.java +++ b/uibase/src/org/compiere/apps/AbstractProcessCtl.java @@ -464,7 +464,7 @@ public abstract class AbstractProcessCtl implements Runnable { if (server != null) { // See ServerBean - m_pi = server.dbProcess(m_pi, ProcedureName); + m_pi = server.dbProcess(Env.getRemoteCallCtx(Env.getCtx()), m_pi, ProcedureName); log.finest("server => " + m_pi); started = true; }