/* * Copyright 2013, WebGate Consulting AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package org.openntf.xpt.agents; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.context.FacesContext; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.openntf.xpt.agents.annotations.XPagesAgent; import org.openntf.xpt.agents.registry.AmgrPropertiesHandler; import org.openntf.xpt.core.dss.changeLog.ChangeLogService; import org.openntf.xpt.core.dss.encryption.EncryptionService; import org.openntf.xpt.core.utils.logging.LoggerFactory; import com.ibm.designer.runtime.Application; import com.ibm.domino.xsp.module.nsf.NSFComponentModule; import com.ibm.domino.xsp.module.nsf.NotesContext; import com.ibm.domino.xsp.module.nsf.SessionCloner; import com.ibm.jscript.std.ObjectObject; import com.ibm.jscript.types.FBSNull; import com.ibm.jscript.types.FBSNumber; import com.ibm.jscript.types.FBSString; import com.ibm.jscript.types.FBSUtility; import com.ibm.jscript.types.FBSValue; import com.ibm.xsp.application.ApplicationEx; import com.ibm.xsp.application.events.ApplicationListener2; public abstract class XPageAgentRegistry implements ApplicationListener2 { private static final String XPAGEAGENT_SERVICE_KEY = "xpt.agent.registry"; // $NON-NLS-1$ private final HashMap<String, XPageAgentEntry> m_Agents = new HashMap<String, XPageAgentEntry>(); private final HashMap<String, XPageAgentJob> m_RunningJobs = new HashMap<String, XPageAgentJob>(); private final HashMap<String, HashMap<String, String>> m_ExecutionPropertyRegistry = new HashMap<String, HashMap<String, String>>(); private final Map<String,Map<String,Object>> m_ExecutionPropertyRegistryExtnd = new HashMap<String, Map<String,Object>>(); private AmgrPropertiesHandler m_AgentRunProperties; private Logger m_Logger;; private String m_DatabasePath; abstract public void registerAgents(); public void addXPageAgent(XPageAgentEntry en) { m_Agents.put(en.getAlias(), en); } public XPageAgentEntry getXPageAgent(String strAlias) { if (m_AgentRunProperties == null) { initAgentRunProperties(); } applyARP(); return m_Agents.get(strAlias); } public int checkSchedule(FacesContext fc) { int nCount = 0; if (m_Agents == null) { return nCount; } if (m_AgentRunProperties == null) { initAgentRunProperties(); } applyARP(); m_Logger.info("checkSchedule"); for (XPageAgentEntry agentEntry : m_Agents.values()) { if (agentEntry.readyToExecuteScheduled()) { nCount++; m_Logger.info("Execute: " + agentEntry.getAlias()); initExecutionBE(agentEntry, fc); } } return nCount; } public String executeJobUI(String strAgentAlias, String strExectuionPropertiesID) { if (m_Agents == null) { return "<no agents>"; } if (!m_Agents.containsKey(strAgentAlias)) { return "<agent " + strAgentAlias + " not found>"; } // CHECK if a possible Encryption Provider is loaded EncryptionService.getInstance().agentLoadProvider(); // CHECK if a possible ChangLogProvider is loaded ChangeLogService.getInstance().getChangeLogProcessors(); XPageAgentEntry en = m_Agents.get(strAgentAlias); try { m_Logger.info("Agent found with alias: " + en.getAlias()); final XPageAgentJob jbCurrent = buildAgentClass(en, FacesContext.getCurrentInstance()); m_RunningJobs.put(jbCurrent.getJobID(), jbCurrent); jbCurrent.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { m_RunningJobs.remove(jbCurrent.getJobID()); } }); if (strExectuionPropertiesID != null) { jbCurrent.setExecutionProperties(m_ExecutionPropertyRegistry.get(strExectuionPropertiesID)); } AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { try { m_Logger.info("Execution scheduled"); jbCurrent.schedule(); } catch (Exception e) { e.printStackTrace(); } return null; } }); deleteExecutionProperties(strExectuionPropertiesID); return jbCurrent.getJobID(); } catch (Exception e) { m_Logger.log(Level.SEVERE, "Error in executeUI:", e); } return "<unkown error>"; } public XPageAgentJob buildAgentClass(XPageAgentEntry agenEntry, FacesContext fc) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { XPageAgentJob jbCurrent = null; Class<?>[] clArgs = new Class<?>[1]; clArgs[0] = String.class; Constructor<?> ct = agenEntry.getAgent().getConstructor(clArgs); Object[] obArgs = new Object[1]; obArgs[0] = agenEntry.getTitle(); jbCurrent = (XPageAgentJob) ct.newInstance(obArgs); jbCurrent.setExecMode(agenEntry.getExecutionMode()); jbCurrent.setDatabasePath(m_DatabasePath); jbCurrent.initCode(NotesContext.getCurrent().getModule(), SessionCloner.getSessionCloner(), fc); return jbCurrent; } private void initExecutionBE(final XPageAgentEntry agentEntry, FacesContext fc) { try { final XPageAgentJob jbCurrent = buildAgentClass(agentEntry, fc); agentEntry.runScheduled(); m_RunningJobs.put(jbCurrent.getJobID(), jbCurrent); jbCurrent.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { m_RunningJobs.remove(jbCurrent.getJobID()); agentEntry.endSchedules(); } }); AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { jbCurrent.schedule(1000); return null; } }); } catch (Exception e) { m_Logger.log(Level.SEVERE, "Error during initExcecutionBE: ", e); } } @SuppressWarnings("unchecked") public void initAgent(Class<?> aAgent) { try { if (aAgent.isAnnotationPresent(XPagesAgent.class)) { XPagesAgent xag = aAgent.getAnnotation(XPagesAgent.class); XPageAgentEntry age = XPageAgentEntry.buildXPagesAgentEntry((Class<XPageAgentJob>) aAgent, xag, false); addXPageAgent(age); } } catch (Exception e) { e.printStackTrace(); } } public void reshedJob() { } @Override public void applicationCreated(ApplicationEx app) { try { m_Logger = LoggerFactory.getLogger(this.getClass().getCanonicalName()); m_Logger.info("App started"); Application.get().putObject(XPAGEAGENT_SERVICE_KEY, this); initApplication(); } catch (Exception e) { e.printStackTrace(); } } private void initApplication() { NSFComponentModule moduleCurrent = NotesContext.getCurrent().getModule(); m_DatabasePath = moduleCurrent.getDatabasePath(); m_Logger.info("MODUL - getDatabasePath(): " + moduleCurrent.getDatabasePath()); registerAgents(); m_Logger.info(m_Agents.size() + " Agents registered"); } @Override public void applicationDestroyed(ApplicationEx arg0) { m_Logger.info("Application unloaded."); } @Override public void applicationRefreshed(ApplicationEx arg0) { try { m_Logger.info("Application refreshed."); Application.get().putObject(XPAGEAGENT_SERVICE_KEY, this); initApplication(); } catch (Exception e) { e.printStackTrace(); } } public static XPageAgentRegistry getInstance(Application app) { XPageAgentRegistry f = (XPageAgentRegistry) app.getObject(XPAGEAGENT_SERVICE_KEY); return f; } public static XPageAgentRegistry getInstance() { return getInstance(Application.get()); } public FBSValue getJobStatus(String strJOBID) { try { if (m_RunningJobs.containsKey(strJOBID)) { XPageAgentJob job = m_RunningJobs.get(strJOBID); ObjectObject objRC = new ObjectObject(); objRC.put("status", FBSUtility.wrap(job.getAgentTaskStatus().toString())); objRC.put("title", FBSUtility.wrap(job.getName())); objRC.put("taskCompletion", FBSUtility.wrap(job.getTaskCompletion())); objRC.put("progressMessage", FBSUtility.wrap(job.getCurrentTaskStatus())); return objRC; } else { ObjectObject objRC = new ObjectObject(); objRC.put("status", FBSUtility.wrap("nojob")); objRC.put("title", FBSString.emptyString); objRC.put("taskCompletion", FBSNumber.Zero); objRC.put("progressMessage", FBSString.emptyString); return objRC; } } catch (Exception e) { e.printStackTrace(); } return FBSNull.nullValue; } public String addExecutionProperties(HashMap<String, String> properties) { String strKey = UUID.randomUUID().toString(); m_ExecutionPropertyRegistry.put(strKey, properties); return strKey; } public void deleteExecutionProperties(String strKey) { m_ExecutionPropertyRegistry.remove(strKey); } public List<XPageAgentEntry> getAllAgents() { if (m_AgentRunProperties == null) { initAgentRunProperties(); } applyARP(); return new ArrayList<XPageAgentEntry>(m_Agents.values()); } private void initAgentRunProperties() { try { m_AgentRunProperties = new AmgrPropertiesHandler(); } catch (Exception e) { e.printStackTrace(); } } private void applyARP() { for (XPageAgentEntry ape : m_Agents.values()) { if (ape.getExecutionMode().isScheduled()) { if ("ON".equalsIgnoreCase(m_AgentRunProperties.getProperty(ape.getAlias())) && !ape.isActive()) { ape.setActive(true); } } } } private void saveARP() { try { m_AgentRunProperties.saveProperties(); } catch (Exception e) { e.printStackTrace(); } } public void activateAgent(String strAgent, FacesContext fc) { XPageAgentEntry agentEntry = m_Agents.get(strAgent); if (agentEntry != null) { agentEntry.setActive(true); m_AgentRunProperties.setProperty(strAgent, "ON"); if (agentEntry.readyToExecuteScheduled()) { initExecutionBE(agentEntry, fc); } saveARP(); } } public void deActivateAgent(String strAgent) { XPageAgentEntry age = m_Agents.get(strAgent); if (age != null) { age.setActive(false); m_AgentRunProperties.setProperty(strAgent, "OFF"); saveARP(); } } public String addExecutionPropertiesExtnd(Map<String, Object> properties) { String strKey = UUID.randomUUID().toString(); m_ExecutionPropertyRegistryExtnd.put(strKey, properties); return strKey; } public String executeJobUIExtnd(String strAgentAlias, String strExectuionPropertiesID) { if (!m_Agents.containsKey(strAgentAlias)) { return "<agent " + strAgentAlias + " not found>"; } // CHECK if a possible Encryption Provider is loaded EncryptionService.getInstance().agentLoadProvider(); // CHECK if a possible ChangLogProvider is loaded ChangeLogService.getInstance().getChangeLogProcessors(); XPageAgentEntry en = m_Agents.get(strAgentAlias); try { m_Logger.info("Agent found with alias: " + en.getAlias()); final XPageAgentJob jbCurrent = buildAgentClass(en, FacesContext.getCurrentInstance()); m_RunningJobs.put(jbCurrent.getJobID(), jbCurrent); jbCurrent.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { m_RunningJobs.remove(jbCurrent.getJobID()); } }); if (strExectuionPropertiesID != null) { jbCurrent.setExtendedExecutionProperties(m_ExecutionPropertyRegistryExtnd.get(strExectuionPropertiesID)); } AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { try { m_Logger.info("Execution scheduled"); jbCurrent.schedule(); } catch (Exception e) { e.printStackTrace(); } return null; } }); deleteExecutionPropertiesExtnd(strExectuionPropertiesID); return jbCurrent.getJobID(); } catch (Exception e) { m_Logger.log(Level.SEVERE, "Error in executeUI:", e); } return "<unkown error>"; } public void deleteExecutionPropertiesExtnd(String strKey) { m_ExecutionPropertyRegistryExtnd.remove(strKey); } }