/** * @param aConfiguration * @throws Exception */ public ExtProcessPlugIn(PluginConfiguration aConfiguration) throws Exception { super(aConfiguration); if (mLog.isDebugEnabled()) { mLog.debug("Instantiating External Process plug-in..."); } // specify default name space for file system plugin this.setNamespace(NS_EXTPROCESS); try { mBeanFactory = getConfigBeanFactory(); if (null == mBeanFactory) { mLog.error( "No or invalid spring configuration for external process plug-in, some features may not be available."); } else { mSettings = (Settings) mBeanFactory.getBean("org.jwebsocket.plugins.extprocess.settings"); // replace all alias values with environment variables Map<String, String> lAllowedProgs = mSettings.getAllowedProgs(); for (Entry<String, String> lEntry : lAllowedProgs.entrySet()) { lEntry.setValue(Tools.expandEnvVarsAndProps(lEntry.getValue())); } if (mLog.isInfoEnabled()) { mLog.info("External Process plug-in successfully instantiated."); } } } catch (BeansException lEx) { mLog.error(Logging.getSimpleExceptionMessage(lEx, "instantiating ExtProcess plug-in")); throw lEx; } }
/** @throws ServletException */ @Override public void init() throws ServletException { if (JWebSocketInstance.STARTED == JWebSocketInstance.getStatus()) { mLog = Logging.getLogger(); String lEngineId = getInitParameter(ServletUtils.SERVLET_ENGINE_CONFIG_KEY); if (null == lEngineId) { lEngineId = "http0"; } mEngine = (HTTPEngine) JWebSocketFactory.getEngine(lEngineId); mConnectorsManager = mEngine.getConnectorsManager(); super.init(); if (mLog.isDebugEnabled()) { mLog.debug("Servlet successfully initialized."); } } else { if (!mServerStartupTimeoutConsumed) { try { // waiting 3 seconds for the server startup log( "The request has been paused because the jWebSocket server is not started." + " Waiting for 3 seconds the jWebSocket server startup..."); Thread.sleep(3000); } catch (InterruptedException lEx) { throw new ServletException(lEx); } mServerStartupTimeoutConsumed = true; init(); } String lErrMsg = "The jWebSocket server startup is taking too long or has failed. " + "Request cannot be processed in this moment!"; log(lErrMsg); throw new ServletException(lErrMsg); } }
/** * An object that does the process of loading configuration, initialization of the jWebSocket server * system. * * @author puran * @version $Id: JWebSocketLoader.java 345 2010-04-10 20:03:48Z fivefeetfurther$ */ public final class JWebSocketLoader { private static Logger mLog = Logging.getLogger();; private JWebSocketConfigHandler mConfigHandler = new JWebSocketConfigHandler(); /** * Initialize the jWebSocket Server system * * @param aConfigPath the overridden path to xml config file * @return the initializer object * @throws WebSocketException if there's an exception while initialization */ public final WebSocketInitializer initialize(String aConfigPath) throws WebSocketException { String lConfigPath; if (aConfigPath != null && !"".equals(aConfigPath)) { lConfigPath = Tools.expandEnvVarsAndProps(aConfigPath); if (mLog.isDebugEnabled()) { mLog.debug("Initializing: Using config file '" + aConfigPath + "'..."); } } else { lConfigPath = JWebSocketConfig.getConfigPath(); } if (lConfigPath == null) { throw new WebSocketException( "Either " + JWebSocketServerConstants.JWEBSOCKET_HOME + " variable is not set" + " or jWebSocket.xml file does neither exist at ${" + JWebSocketServerConstants.JWEBSOCKET_HOME + "}/conf nor at ${CLASSPATH}/conf."); } // load the entire settings from the configuration xml file JWebSocketConfig lConfig = loadConfiguration(lConfigPath); // initialize security by using config settings SecurityFactory.initFromConfig(lConfig); WebSocketInitializer lInitializer = new JWebSocketXmlConfigInitializer(lConfig); return lInitializer; } /** * Load all the configurations based on jWebSocket.xml file at the given <tt>configFilePath</tt> * location. * * @param aConfigPath the path to jWebSocket.xml file * @return the web socket config object with all the configuration * @throws WebSocketException if there's any while loading configuration */ public JWebSocketConfig loadConfiguration(final String aConfigPath) throws WebSocketException { JWebSocketConfig lConfig = null; String lMsg; try { InputStream lIS; if (JWebSocketConfig.isLoadConfigFromResource()) { if (mLog.isDebugEnabled()) { mLog.debug("Loading configuration from resource '" + aConfigPath + "..."); } lIS = this.getClass().getResourceAsStream("/" + aConfigPath); } else { if (mLog.isDebugEnabled()) { mLog.debug("Loading configuration from file '" + aConfigPath + "..."); } File lFile = new File(aConfigPath); lIS = new FileInputStream(lFile); } XMLInputFactory lFactory = XMLInputFactory.newInstance(); XMLStreamReader lStreamReader = null; lStreamReader = lFactory.createXMLStreamReader(lIS); lConfig = (JWebSocketConfig) mConfigHandler.processConfig(lStreamReader); if (mLog.isInfoEnabled()) { mLog.info("Configuration successfully loaded from '" + aConfigPath + "'."); } } catch (XMLStreamException lEx) { lMsg = lEx.getClass().getSimpleName() + " occurred while creating XML stream (" + aConfigPath + "): " + lEx.getMessage() + "."; throw new WebSocketException(lMsg); } catch (FileNotFoundException lEx) { lMsg = "jWebSocket config file not found while creating XML stream (" + aConfigPath + "): " + lEx.getMessage() + "."; throw new WebSocketException(lMsg); } return lConfig; } }
/** @author Osvaldo Aguilar Lauzurique */ public abstract class BaseQuota implements IQuota { /** */ protected static Logger mLog = Logging.getLogger(); /** */ protected IQuotaStorage mQuotaStorage; /** */ protected String mQuotaType; /** */ protected String mQuotaIdentifier; /** */ protected long mDefaultReduceValue; /** */ protected long mDefaultIncrease; @Override public long getDefaultReduceValue() { return mDefaultReduceValue; } /** @return */ public long getDefaultIncrease() { return mDefaultIncrease; } /** @param aDefaultReduceValue */ public void setDefaultReduceValue(long aDefaultReduceValue) { this.mDefaultReduceValue = aDefaultReduceValue; } /** @param mQuotaIdentifier */ public void setQuotaIdentifier(String mQuotaIdentifier) { this.mQuotaIdentifier = mQuotaIdentifier; } /** @param aDefaultIncrease */ public void setDefaultIncreaseValue(long aDefaultIncrease) { this.mDefaultIncrease = aDefaultIncrease; } /** @param aQuotaType */ public void setQuotaType(String aQuotaType) { this.mQuotaType = aQuotaType; } @Override public IQuotaStorage getStorage() { return mQuotaStorage; } @Override public String getType() { return mQuotaType; } @Override public void setStorage(IQuotaStorage aQuotaStorage) { this.mQuotaStorage = aQuotaStorage; try { this.mQuotaStorage.initialize(); } catch (Exception aExp) { mLog.error( "Error to initialize the quota storage, the following" + " error was capture on the server: " + aExp.getMessage()); } } /** * @param aInstance * @param aNameSpace * @param aInstanceType * @param aActions * @return */ @Override public IQuotaSingleInstance getQuota( String aInstance, String aNameSpace, String aInstanceType, String aActions) { IQuotaSingleInstance lQResult; String lUuid; try { lUuid = getQuotaUuid(mQuotaIdentifier, aNameSpace, aInstance, aInstanceType, aActions); } catch (Exception e) { lUuid = "not-found"; } // Asking if the user has as part of a group quota that belong to a group. if (lUuid.equals("not-found") && aInstanceType.equals("User")) { List<IQuotaSingleInstance> lQuotasGroup = mQuotaStorage.getQuotasByIdentifierNSInstanceType(mQuotaIdentifier, aNameSpace, "Group"); lQResult = findQuotaByInstance(lQuotasGroup, aInstance, aActions); if (lQResult == null) { List<IQuotaSingleInstance> lQuotasUser = mQuotaStorage.getQuotasByIdentifierNSInstanceType(mQuotaIdentifier, aNameSpace, "User"); lQResult = findQuotaByInstance(lQuotasUser, aInstance, aActions); } return lQResult; } else { return getQuota(lUuid); } } /** * @param aInstance * @param aNameSpace * @param aInstanceType * @return */ @Override public List<IQuotaSingleInstance> getQuotas( String aInstance, String aNameSpace, String aInstanceType) { List<IQuotaSingleInstance> lQuotasNs = mQuotaStorage.getQuotasByNs(mQuotaIdentifier, aNameSpace); // if there is not quota for this namespace, there will not exists a quota for the instance if (lQuotasNs.isEmpty()) { return lQuotasNs; } return (FastList<IQuotaSingleInstance>) findQuotasByInstance(lQuotasNs, aInstance); } /** * get a IQuotaSingleInstance list and an string with the instance and return all quotas about * belong to this instance. * * @return */ private List<IQuotaSingleInstance> findQuotasByInstance( List<IQuotaSingleInstance> aQuotas, String aInstance) { List<IQuotaSingleInstance> lQResult = new FastList<IQuotaSingleInstance>(); if (aQuotas.size() > 0) { IQuotaSingleInstance lQtmp = null; for (Iterator<IQuotaSingleInstance> it = aQuotas.iterator(); it.hasNext(); ) { IQuotaSingleInstance lQuotaSingle = it.next(); QuotaChildSI lChild; lChild = lQuotaSingle.getChildQuota(aInstance); if (null != lChild) { if (lQuotaSingle.getInstanceType().equals("Group")) { lQtmp = QuotaHelper.factorySingleInstance( lChild.getValue(), lChild.getInstance(), lChild.getUuid(), lQuotaSingle.getNamespace(), lQuotaSingle.getQuotaType(), lQuotaSingle.getQuotaIdentifier(), lChild.getInstanceType(), lQuotaSingle.getActions()); } if (lQuotaSingle.getInstanceType().equals("User")) { lQtmp = QuotaHelper.factorySingleInstance( lQuotaSingle.getvalue(), lChild.getInstance(), lChild.getUuid(), lQuotaSingle.getNamespace(), lQuotaSingle.getQuotaType(), lQuotaSingle.getQuotaIdentifier(), lChild.getInstanceType(), lQuotaSingle.getActions()); } if (lQtmp != null) { lQResult.add(lQtmp); } } } } return lQResult; } /** * get a IQuotaSingleInstance list and an string with the instanceType and return the * IQuotaSingleInstance. * * @return */ private IQuotaSingleInstance findQuotaByInstance( List<IQuotaSingleInstance> aQuotas, String aInstance, String aActions) { IQuotaSingleInstance lQResult = null; for (Iterator<IQuotaSingleInstance> it = aQuotas.iterator(); it.hasNext(); ) { IQuotaSingleInstance lQuotaSingle = it.next(); QuotaChildSI lChild; lChild = lQuotaSingle.getChildQuota(aInstance); if (null != lChild) { if (!lQuotaSingle.getActions().equals(aActions)) { continue; } if (lQuotaSingle.getInstanceType().equals("Group")) { lQResult = QuotaHelper.factorySingleInstance( lChild.getValue(), lChild.getInstance(), lChild.getUuid(), lQuotaSingle.getNamespace(), lQuotaSingle.getQuotaType(), lQuotaSingle.getQuotaIdentifier(), lChild.getInstanceType(), lQuotaSingle.getActions()); } if (lQuotaSingle.getInstanceType().equals("User")) { lQResult = QuotaHelper.factorySingleInstance( lQuotaSingle.getvalue(), lChild.getInstance(), lChild.getUuid(), lQuotaSingle.getNamespace(), lQuotaSingle.getQuotaType(), lQuotaSingle.getQuotaIdentifier(), lChild.getInstanceType(), lQuotaSingle.getActions()); } return lQResult; } } return null; } /** * @param aUuid * @return */ @Override public IQuotaSingleInstance getQuota(String aUuid) { IQuotaSingleInstance lQuotaInstance = (IQuotaSingleInstance) mQuotaStorage.getQuotaByUuid(aUuid); return lQuotaInstance; } /** * @param aUuid * @param aInstance * @return */ @Override public IQuotaSingleInstance getQuota(String aUuid, String aInstance) { IQuotaSingleInstance lQuotaInstance = (IQuotaSingleInstance) mQuotaStorage.getQuotaByUuid(aUuid); if (lQuotaInstance.getInstance().equals(aInstance)) { return lQuotaInstance; } else { QuotaChildSI lQuotaChild = lQuotaInstance.getChildQuota(aInstance); if (null != lQuotaChild) { IQuotaSingleInstance lSingle = new QuotaBaseInstance( lQuotaChild.getValue(), aInstance, aUuid, lQuotaInstance.getNamespace(), lQuotaInstance.getQuotaType(), lQuotaInstance.getQuotaIdentifier(), lQuotaChild.getInstanceType(), lQuotaInstance.getActions()); return lSingle; } } return null; } /** @return */ @Override public String getIdentifier() { return mQuotaIdentifier; } /** * @param aUuid * @param aAmount * @return */ @Override public abstract long reduceQuota(String aUuid, long aAmount); /** * @param aInstance * @param aNameSpace * @param aInstanceType * @param aActions * @param aAmount * @return */ @Override public long reduceQuota( String aInstance, String aNameSpace, String aInstanceType, String aActions, long aAmount) { IQuotaSingleInstance lQSingle = getQuota(aInstance, aNameSpace, aInstanceType, aActions); long lResult = -1; if (lQSingle != null) { long lReduce = lQSingle.getvalue() - aAmount; if (lReduce <= -1) { lReduce = -1; } lResult = setQuota( lQSingle.getInstance(), aNameSpace, lQSingle.getInstanceType(), aActions, lReduce); } return lResult; } /** * @param aUuid * @return */ @Override public long reduceQuota(String aUuid) { return reduceQuota(aUuid, mDefaultReduceValue); } /** * @param aUuid * @return */ @Override public String getActions(String aUuid) { String lActions = this.getStorage().getActions(aUuid); return lActions; } /** * @param aInstance * @param aNameSpace * @param aInstanceType * @param aActions * @param aAmount * @return */ @Override public long increaseQuota( String aInstance, String aNameSpace, String aInstanceType, String aActions, long aAmount) { IQuotaSingleInstance lQSingle = getQuota(aInstance, aNameSpace, aInstanceType, aActions); long lResult = -1; if (lQSingle != null) { long lReduce = lQSingle.getvalue() + aAmount; lResult = setQuota( lQSingle.getInstance(), aNameSpace, lQSingle.getInstanceType(), aActions, lReduce); } return lResult; } /** * @param aUuid * @param aAmount * @return */ @Override public long increaseQuota(String aUuid, long aAmount) { long lValue = getQuota(aUuid).getvalue(); return getStorage().update(aUuid, lValue + aAmount); } /** * @param aInstance * @param aNameSpace * @param aInstanceType * @param aActions * @param aAmount * @return */ @Override public long setQuota( String aInstance, String aNameSpace, String aInstanceType, String aActions, long aAmount) { IQuotaSingleInstance lQSingle = getQuota(aInstance, aNameSpace, aInstanceType, aActions); // if the instanceType request is Group then update the father quota. if (lQSingle.getInstanceType().equals("Group") && aInstanceType.equals("Group")) { return setQuota(lQSingle.getUuid(), aAmount); } /** * if the quota type of the getQuota method is User, it is possible that this quota be part of a * father quota. */ if (lQSingle.getInstanceType().equals("User")) { if (mQuotaStorage.quotaExist( aNameSpace, mQuotaIdentifier, lQSingle.getInstance(), lQSingle.getActions())) { return setQuota(lQSingle.getUuid(), aAmount); } else { IQuotaSingleInstance lSingleInstance = mQuotaStorage.getQuotaByUuid(lQSingle.getUuid()); QuotaChildSI lQChild = lSingleInstance.getChildQuota(lQSingle.getInstance()); lQChild.setValue(aAmount); if (lSingleInstance.getInstanceType().equals("User")) { return mQuotaStorage.update(lSingleInstance.getUuid(), lQChild.getValue()); } return mQuotaStorage.update(lQChild); } } else { return -1; } } /** * @param aUuid * @param aAmount * @return */ @Override public long setQuota(String aUuid, long aAmount) { return getStorage().update(aUuid, aAmount); } /** * @param aUuid * @param aInstance * @param aInstanceType * @throws Exception */ @Override public void register(String aUuid, String aInstance, String aInstanceType) throws Exception { if (!mQuotaStorage.quotaExist(aUuid)) { throw new ExceptionQuotaNotFound(aUuid); } // Creating the child Quota IQuotaSingleInstance lSingleInstance = mQuotaStorage.getQuotaByUuid(aUuid); if (lSingleInstance.getInstance().equals(aInstance)) { throw new ExceptionQuotaAlreadyExist(aInstance); } QuotaChildSI lChildQuota = new QuotaChildSI(aInstance, aUuid, aInstanceType); // if a register quota occur over a quota with InstanceType user // The quota is shared between the users of this quota, by this reason // The quota is register to the parent quota with 0 as their own value. if (lSingleInstance.getInstanceType().equals("User")) { lChildQuota.setValue(0); } else { lChildQuota.setValue(lSingleInstance.getvalue()); } boolean lResult; lResult = lSingleInstance.addChildQuota(lChildQuota); if (lResult == true) { lResult = mQuotaStorage.save(lChildQuota); } else { throw new ExceptionQuotaAlreadyExist(aInstance); } } /** * @param aInstance * @param aNameSpace * @param aUuid * @param aAmount * @param aInstanceType * @param aQuotaType * @param aQuotaIdentifier * @param aActions * @throws Exception */ @Override public void create( String aInstance, String aNameSpace, String aUuid, long aAmount, String aInstanceType, String aQuotaType, String aQuotaIdentifier, String aActions) throws Exception { if (mQuotaStorage.quotaExist(aNameSpace, aQuotaIdentifier, aInstance, aActions)) { throw new ExceptionQuotaAlreadyExist( mQuotaStorage.getUuid(aQuotaIdentifier, aNameSpace, aInstance, aInstanceType, aActions)); } IQuotaSingleInstance lSingleQuota; lSingleQuota = new QuotaCountdownSI( aAmount, aInstance, aUuid, aNameSpace, aQuotaType, aQuotaIdentifier, aInstanceType, aActions); mQuotaStorage.save(lSingleQuota); } /** * @param aInstance * @param aUuid * @throws ExceptionQuotaNotFound */ @Override public void unregister(String aInstance, String aUuid) throws ExceptionQuotaNotFound { if (!mQuotaStorage.quotaExist(aUuid)) { throw new ExceptionQuotaNotFound(aUuid); } IQuotaSingleInstance lQSingle = getQuota(aUuid); if (lQSingle.getInstance().equals(aInstance)) { mQuotaStorage.remove(aUuid, aInstance); } else { QuotaChildSI lChild = lQSingle.getChildQuota(aInstance); if (lChild != null) { mQuotaStorage.remove(lChild); } } } /** * @param aInstance * @param aNameSpace * @param aInstanceType * @param aActions * @throws ExceptionQuotaNotFound */ @Override public void unregister(String aInstance, String aNameSpace, String aInstanceType, String aActions) throws ExceptionQuotaNotFound { String lUuid = getQuotaUuid(mQuotaIdentifier, aNameSpace, aInstance, aInstanceType, aActions); unregister(lUuid, aInstance); } /** * @param aNamespace * @param aId * @return */ @Override public List<String> getRegisteredInstances(String aNamespace, String aId) { return new FastList<String>(); } /** * @param aNamespace * @return */ @Override public List<String> getRegisterdQuotas(String aNamespace) { return new FastList<String>(); } /** * @param aQuotaIdentifier * @param aNamespace * @param aInstance * @param aInstanceType * @param aActions * @return */ @Override public String getQuotaUuid( String aQuotaIdentifier, String aNamespace, String aInstance, String aInstanceType, String aActions) { try { return mQuotaStorage.getUuid( aQuotaIdentifier, aNamespace, aInstance, aInstanceType, aActions); } catch (ExceptionQuotaNotFound ex) { return "not-found"; } } }
/** * This works OK, the only pending question is that the write method of the native OutputStream * never gets locked as expected. * * <p>Advises: - Notify the connector stopped event in a thread pool instead of the same thread - * Check the connection state before send a packet * * @author Rolando Santamaria Maso * @author Alexander Schulze */ public class TimeoutOutputStreamNIOWriter { private static final Logger mLog = Logging.getLogger(); private static final int DEFAULT_TIME_OUT_TERMINATION_THREAD = 1000; /** Singleton Timer instance to control all timeout tasks */ private static int mTimeout = DEFAULT_TIME_OUT_TERMINATION_THREAD; // can be set to "true" for heavy debugging purposes private static final boolean mIsDebug = false; // the size of this executor service should be adjusted to the maximum // of expected client send operations that concurrently might get // to a timeout case. private static ExecutorService mPool = null; private static final Object mPoolSync = new Object(); private OutputStream mOut = null; private InputStream mIn = null; private WebSocketConnector mConnector = null; private static boolean mStarted = false; private static Timer mTimer; /** * @param aNumWorkers * @param aTimeout */ public static void start(int aNumWorkers, int aTimeout) { mTimer = Tools.getTimer(); mPool = Executors.newFixedThreadPool( aNumWorkers, new ThreadFactory() { @Override public Thread newThread(Runnable aRunnable) { return new Thread(aRunnable, "jWebSocket TCP-Engine NIO writer"); } }); mTimeout = aTimeout; mStarted = true; } /** */ public static void stop() { synchronized (mPoolSync) { if (mStarted) { mPool.shutdownNow(); mStarted = false; } } } /** * @param aConnector * @param aIn * @param aOut */ public TimeoutOutputStreamNIOWriter( WebSocketConnector aConnector, InputStream aIn, OutputStream aOut) { mConnector = aConnector; mIn = aIn; mOut = aOut; } /** @return */ public static ExecutorService getPool() { return mPool; } /** @param aTimeout */ public static void setTimeout(int aTimeout) { mTimeout = aTimeout; } /** @return */ public static int getTimeout() { return mTimeout; } /** Write operation thread to execute write operations in non-blocking mode. */ class SendOperation implements Runnable { private final WebSocketPacket mPacket; private boolean mSent = false; public InputStream getIn() { return mIn; } public OutputStream getOut() { return mOut; } public boolean isDone() { return mSent; } public SendOperation(WebSocketPacket aDataPacket) { mPacket = aDataPacket; } @Override public void run() { // @TODO This always is being executed quickly even when the connector get's stopped // this sends the packet to the socket output stream if (mIsDebug && mLog.isDebugEnabled()) { mLog.debug( "Physically sending packet to '" + mConnector.getId() + "' under timeout control..."); } // sending packet in blocking mode ((TCPConnector) mConnector)._sendPacket(mPacket); // this cancels the timeout task in case // the send operation did not block for the given timeout if (mIsDebug && mLog.isDebugEnabled()) { mLog.debug( "Cancelling timeout control for '" + mConnector.getId() + "' because packet had been sent properly..."); } // setting the sent flag to true mSent = true; } } /** * Send a data packet with timeout control. * * @param aDataPacket */ public void sendPacket(WebSocketPacket aDataPacket) { if (mIsDebug && mLog.isDebugEnabled()) { mLog.debug("Scheduling send operation to '" + mConnector.getId() + "'..."); } synchronized (mPoolSync) { if (mPool.isTerminated() || mPool.isShutdown()) { mLog.warn("Sender thread pool is terminated or shutdown already, skipping send operation."); return; } // create a timer task to send the packet final SendOperation lSend = new SendOperation(aDataPacket); // create a timeout timer task to cancel the send operation in case of disconnection mTimer.schedule( new JWSTimerTask() { @Override public void runTask() { try { if (!lSend.isDone()) { // close the outbound stream to fire exception // timed out write operation if (mIsDebug && mLog.isDebugEnabled()) { mLog.debug( "Closing stream to '" + mConnector.getId() + "' connector due to timeout..."); } lSend.getIn().close(); lSend.getOut().close(); } } catch (IOException lEx) { // TODO check this } } }, mTimeout); // finally execute the send operation mPool.execute(lSend); } } }
/** @author aschulze */ public class ExtProcessPlugIn extends TokenPlugIn { private static final Logger mLog = Logging.getLogger(); /** */ public static final String NS_EXTPROCESS = JWebSocketServerConstants.NS_BASE + ".plugins.extprocess"; private static final String VERSION = "1.0.0"; private static final String VENDOR = JWebSocketCommonConstants.VENDOR_CE; private static final String LABEL = "jWebSocket ExtProcessPlugIn"; private static final String COPYRIGHT = JWebSocketCommonConstants.COPYRIGHT_CE; private static final String LICENSE = JWebSocketCommonConstants.LICENSE_CE; private static final String DESCRIPTION = "jWebSocket ExtProcessPlugIn - Community Edition"; /** */ protected ApplicationContext mBeanFactory; /** */ protected Settings mSettings; /** * @param aConfiguration * @throws Exception */ public ExtProcessPlugIn(PluginConfiguration aConfiguration) throws Exception { super(aConfiguration); if (mLog.isDebugEnabled()) { mLog.debug("Instantiating External Process plug-in..."); } // specify default name space for file system plugin this.setNamespace(NS_EXTPROCESS); try { mBeanFactory = getConfigBeanFactory(); if (null == mBeanFactory) { mLog.error( "No or invalid spring configuration for external process plug-in, some features may not be available."); } else { mSettings = (Settings) mBeanFactory.getBean("org.jwebsocket.plugins.extprocess.settings"); // replace all alias values with environment variables Map<String, String> lAllowedProgs = mSettings.getAllowedProgs(); for (Entry<String, String> lEntry : lAllowedProgs.entrySet()) { lEntry.setValue(Tools.expandEnvVarsAndProps(lEntry.getValue())); } if (mLog.isInfoEnabled()) { mLog.info("External Process plug-in successfully instantiated."); } } } catch (BeansException lEx) { mLog.error(Logging.getSimpleExceptionMessage(lEx, "instantiating ExtProcess plug-in")); throw lEx; } } @Override public String getVersion() { return VERSION; } @Override public String getLabel() { return LABEL; } @Override public String getDescription() { return DESCRIPTION; } @Override public String getVendor() { return VENDOR; } @Override public String getCopyright() { return COPYRIGHT; } @Override public String getLicense() { return LICENSE; } @Override public String getNamespace() { return NS_EXTPROCESS; } @Override public synchronized void engineStarted(WebSocketEngine aEngine) {} @Override public synchronized void engineStopped(WebSocketEngine aEngine) {} @Override public void processToken(PlugInResponse aResponse, WebSocketConnector aConnector, Token aToken) { String lType = aToken.getType(); String lNS = aToken.getNS(); if (lType != null && getNamespace().equals(lNS)) { if (lType.equals("call")) { call(aConnector, aToken); } } } @Override public Token invoke(WebSocketConnector aConnector, Token aToken) { String lType = aToken.getType(); String lNS = aToken.getNS(); if (lType != null && getNamespace().equals(lNS)) { /* if (lType.equals("getFilelist")) { return getFilelist(aConnector.getUsername(), aToken); } else if (lType.equals("getAliasPath")) { String lTargetAlias = aToken.getString("alias"); Token lToken = TokenFactory.createToken(); lToken.setString("aliasPath", getAliasPath(aConnector, lTargetAlias)); return lToken; } */ } return null; } private void call(WebSocketConnector aConnector, Token aToken) { TokenServer lServer = getServer(); Token lResponse = createResponse(aToken); // check if user is allowed to run 'exists' command /* if (!hasAuthority(aConnector, NS_EXTPROCESS + ".call")) { if (mLog.isDebugEnabled()) { mLog.debug("Returning 'Access denied'..."); } lServer.sendToken(aConnector, lServer.createAccessDenied(aToken)); return; } */ String lAlias = aToken.getString("alias"); if (null == lAlias) { lResponse.setInteger("code", -1); lResponse.setString("msg", "No alias passed."); lServer.sendToken(aConnector, lResponse); return; } String lCmdLine = mSettings.getAllowedProgs().get(lAlias); if (null == lCmdLine) { lResponse.setInteger("code", -1); lResponse.setString("msg", "Alias '" + lAlias + "' not found."); lServer.sendToken(aConnector, lResponse); return; } List<?> lArgs = aToken.getList("args"); if (mLog.isDebugEnabled()) { mLog.debug( "Processing 'call'" + " (alias: " + lAlias + ", args: " + StringUtils.collectionToDelimitedString(lArgs, ", ") + ")..."); } String[] lCmdTokens = StringUtils.tokenizeToStringArray(lCmdLine, " ", true, false); List<String> lCmd = new ArrayList<String>(); for (String lCmdToken : lCmdTokens) { for (int lArgIdx = 0; lArgIdx < lArgs.size(); lArgIdx++) { lCmdToken = lCmdToken.replace("${" + (lArgIdx + 1) + "}", lArgs.get(lArgIdx).toString()); } lCmd.add(lCmdToken); } ProcessBuilder lProcBuilder = new ProcessBuilder(lCmd); // Map<String, String> lEnv = lProcBuilder.environment(); lProcBuilder.directory(new File(System.getenv("temp"))); try { if (mLog.isDebugEnabled()) { mLog.debug("Directory: " + System.getenv("temp")); } final Process process = lProcBuilder.start(); InputStream lIS = process.getInputStream(); InputStreamReader lISR = new InputStreamReader(lIS); BufferedReader lBR = new BufferedReader(lISR); String lLine; StringBuilder lStrBuf = new StringBuilder(); while ((lLine = lBR.readLine()) != null) { Token lEventToken = TokenFactory.createToken(getNamespace(), "event"); lEventToken.setString("line", lLine); lStrBuf.append(lLine).append("\n"); lServer.sendToken(aConnector, lEventToken); } lResponse.setInteger("exitCode", process.exitValue()); if (mLog.isDebugEnabled()) { mLog.debug("Sent '" + lStrBuf.toString().replace("\n", "\\n") + "'."); } } catch (IOException lEx) { lResponse.setInteger("code", -1); String lMsg = Logging.getSimpleExceptionMessage(lEx, "calling external process"); lResponse.setString("msg", lMsg); mLog.error(lMsg); } lServer.sendToken(aConnector, lResponse); } }
private void call(WebSocketConnector aConnector, Token aToken) { TokenServer lServer = getServer(); Token lResponse = createResponse(aToken); // check if user is allowed to run 'exists' command /* if (!hasAuthority(aConnector, NS_EXTPROCESS + ".call")) { if (mLog.isDebugEnabled()) { mLog.debug("Returning 'Access denied'..."); } lServer.sendToken(aConnector, lServer.createAccessDenied(aToken)); return; } */ String lAlias = aToken.getString("alias"); if (null == lAlias) { lResponse.setInteger("code", -1); lResponse.setString("msg", "No alias passed."); lServer.sendToken(aConnector, lResponse); return; } String lCmdLine = mSettings.getAllowedProgs().get(lAlias); if (null == lCmdLine) { lResponse.setInteger("code", -1); lResponse.setString("msg", "Alias '" + lAlias + "' not found."); lServer.sendToken(aConnector, lResponse); return; } List<?> lArgs = aToken.getList("args"); if (mLog.isDebugEnabled()) { mLog.debug( "Processing 'call'" + " (alias: " + lAlias + ", args: " + StringUtils.collectionToDelimitedString(lArgs, ", ") + ")..."); } String[] lCmdTokens = StringUtils.tokenizeToStringArray(lCmdLine, " ", true, false); List<String> lCmd = new ArrayList<String>(); for (String lCmdToken : lCmdTokens) { for (int lArgIdx = 0; lArgIdx < lArgs.size(); lArgIdx++) { lCmdToken = lCmdToken.replace("${" + (lArgIdx + 1) + "}", lArgs.get(lArgIdx).toString()); } lCmd.add(lCmdToken); } ProcessBuilder lProcBuilder = new ProcessBuilder(lCmd); // Map<String, String> lEnv = lProcBuilder.environment(); lProcBuilder.directory(new File(System.getenv("temp"))); try { if (mLog.isDebugEnabled()) { mLog.debug("Directory: " + System.getenv("temp")); } final Process process = lProcBuilder.start(); InputStream lIS = process.getInputStream(); InputStreamReader lISR = new InputStreamReader(lIS); BufferedReader lBR = new BufferedReader(lISR); String lLine; StringBuilder lStrBuf = new StringBuilder(); while ((lLine = lBR.readLine()) != null) { Token lEventToken = TokenFactory.createToken(getNamespace(), "event"); lEventToken.setString("line", lLine); lStrBuf.append(lLine).append("\n"); lServer.sendToken(aConnector, lEventToken); } lResponse.setInteger("exitCode", process.exitValue()); if (mLog.isDebugEnabled()) { mLog.debug("Sent '" + lStrBuf.toString().replace("\n", "\\n") + "'."); } } catch (IOException lEx) { lResponse.setInteger("code", -1); String lMsg = Logging.getSimpleExceptionMessage(lEx, "calling external process"); lResponse.setString("msg", lMsg); mLog.error(lMsg); } lServer.sendToken(aConnector, lResponse); }