001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.core.structure;
034:
035: import com.flexive.core.Database;
036: import com.flexive.core.security.UserTicketImpl;
037: import com.flexive.core.storage.EnvironmentLoader;
038: import com.flexive.core.storage.StorageManager;
039: import com.flexive.shared.CacheAdmin;
040: import com.flexive.shared.EJBLookup;
041: import com.flexive.shared.FxContext;
042: import com.flexive.shared.cache.FxCacheException;
043: import com.flexive.shared.configuration.DivisionData;
044: import com.flexive.shared.exceptions.FxApplicationException;
045: import com.flexive.shared.exceptions.FxInvalidParameterException;
046: import com.flexive.shared.exceptions.FxLoadException;
047: import com.flexive.shared.exceptions.FxNotFoundException;
048: import com.flexive.shared.security.ACL;
049: import com.flexive.shared.security.Mandator;
050: import com.flexive.shared.structure.FxType;
051: import org.apache.commons.logging.Log;
052: import org.apache.commons.logging.LogFactory;
053:
054: import java.sql.Connection;
055: import java.sql.SQLException;
056:
057: /**
058: * Load structure information into the cache
059: *
060: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
061: */
062: public final class StructureLoader {
063: private static final transient Log LOG = LogFactory
064: .getLog(StructureLoader.class);
065:
066: /**
067: * Private c'tor to avoid instantiation
068: */
069: private StructureLoader() {
070: }
071:
072: /**
073: * (Re)Load the FxStructure runtime for a given division and put it into the cache
074: *
075: * @param divisionId division to load
076: * @param forceReload load even if exists
077: * @param _con optional open connection
078: * @throws FxCacheException on errors
079: * @throws FxLoadException on errors
080: */
081: public static void load(int divisionId, boolean forceReload,
082: Connection _con) throws FxCacheException, FxLoadException {
083: DivisionData dd;
084: try {
085: dd = EJBLookup.getGlobalConfigurationEngine()
086: .getDivisionData(divisionId);
087: if (!dd.isAvailable()) {
088: LOG.error("Division " + divisionId
089: + " is not available!");
090: return;
091: }
092: if (LOG.isDebugEnabled())
093: LOG.debug("Loading environment for division "
094: + divisionId + " (" + dd.getDbVendor() + ": "
095: + dd.getDbVersion() + "), forcing reload: "
096: + forceReload);
097: } catch (Exception e) {
098: LOG.error(e, e);
099: throw new FxLoadException(e);
100: }
101: EnvironmentLoader loader;
102: try {
103: loader = StorageManager.getEnvironmentLoader(dd);
104: } catch (FxNotFoundException e) {
105: throw new FxLoadException(e);
106: }
107: Connection con = _con;
108: try {
109: long time = System.currentTimeMillis();
110: try {
111: if (con == null)
112: con = FxEnvironmentUtils
113: .getDbConnection(divisionId);
114: } catch (SQLException e) {
115: LOG.error(e, e);
116: return;
117: }
118: FxEnvironmentImpl environment = (FxEnvironmentImpl) FxEnvironmentUtils
119: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
120: CacheAdmin.ENVIRONMENT_RUNTIME);
121: if (environment != null && !forceReload)
122: return;
123: environment = new FxEnvironmentImpl();
124: environment.setDataTypes(loader.loadDataTypes(con));
125: environment.setAcls(loader.loadACLs(con));
126: environment.setStepDefinitions(loader
127: .loadStepDefinitions(con));
128: environment.setSteps(loader.loadSteps(con));
129: environment.setWorkflows(loader.loadWorkflows(con,
130: environment));
131: environment.setMandators(loader.loadMandators(con));
132: environment.setGroups(loader.loadGroups(con));
133: environment.setSelectLists(loader.loadSelectLists(con,
134: environment));
135: environment.setTypes(loader.loadTypes(con, environment));
136: environment.setProperties(loader.loadProperties(con,
137: environment));
138: environment.setAssignments(loader.loadAssignments(con,
139: environment));
140: environment.setScripts(loader.loadScripts(con));
141: environment.setScriptMappings(loader.loadScriptMapping(con,
142: environment));
143: environment.resolveDependencies();
144: environment.updateTimeStamp();
145: //structure might have been loaded meanwhile on another node - only put it into the cache if forcing
146: if (FxEnvironmentUtils.cacheGet(divisionId,
147: CacheAdmin.ENVIRONMENT_BASE,
148: CacheAdmin.ENVIRONMENT_RUNTIME) == null
149: || forceReload) {
150: FxEnvironmentUtils.cachePut(divisionId,
151: CacheAdmin.ENVIRONMENT_BASE,
152: CacheAdmin.ENVIRONMENT_RUNTIME, environment);
153: if (LOG.isDebugEnabled())
154: LOG.debug("Loaded structure and put into cache in "
155: + (System.currentTimeMillis() - time)
156: + "[ms]");
157: //put a dummy cached entry to create the path to avoid cache warnings if the content cache is
158: //accessed and it does not exist because its empty
159: CacheAdmin.getInstance().put(
160: CacheAdmin.CONTENTCACHE_BASE, -1, null);
161: UserTicketImpl.reloadGuestTicketAssignments(true);
162: }
163: } catch (FxNotFoundException e) {
164: throw new FxLoadException(LOG, e);
165: } catch (FxInvalidParameterException e) {
166: throw new FxLoadException(LOG, e);
167: } finally {
168: if (_con == null)
169: Database.closeObjects(StructureLoader.class, con, null);
170: }
171: }
172:
173: /**
174: * Load all FxStructure runtimes from the registered databases and place them into the cache
175: *
176: * @throws FxCacheException on errors
177: * @throws FxApplicationException on errors
178: */
179: public static void loadAll() throws FxCacheException,
180: FxApplicationException {
181: for (int div : EJBLookup.getGlobalConfigurationEngine()
182: .getDivisionIds())
183: StructureLoader.load(div, false, null);
184: }
185:
186: /**
187: * Reload all workflows for the given division
188: *
189: * @param divisionId the division to reload
190: * @throws FxApplicationException on errors
191: */
192: public static void reloadWorkflows(int divisionId)
193: throws FxApplicationException {
194: long time = System.currentTimeMillis();
195: Connection con = null;
196: try {
197: try {
198: con = FxEnvironmentUtils.getDbConnection(divisionId);
199: } catch (SQLException e) {
200: LOG.error(e);
201: return;
202: }
203: FxEnvironmentImpl structure = ((FxEnvironmentImpl) CacheAdmin
204: .getEnvironment()).deepClone();
205:
206: EnvironmentLoader loader;
207: loader = StorageManager.getEnvironmentLoader(EJBLookup
208: .getGlobalConfigurationEngine().getDivisionData(
209: divisionId));
210: structure.setStepDefinitions(loader
211: .loadStepDefinitions(con));
212: structure.setSteps(loader.loadSteps(con));
213: structure
214: .setWorkflows(loader.loadWorkflows(con, structure));
215: //resync workflows
216: for (FxType type : structure.getTypes(true, true, true,
217: true))
218: type.reloadWorkflow(structure);
219: FxEnvironmentUtils.cachePut(divisionId,
220: CacheAdmin.ENVIRONMENT_BASE,
221: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
222: CacheAdmin.getEnvironment();
223: } catch (FxCacheException e) {
224: LOG.error(e, e);
225: } catch (FxNotFoundException e) {
226: throw new FxLoadException(e);
227: } finally {
228: Database.closeObjects(StructureLoader.class, con, null);
229: }
230: if (LOG.isDebugEnabled())
231: LOG.debug("Reloaded Workflows in "
232: + (System.currentTimeMillis() - time) + "[ms]");
233: }
234:
235: /**
236: * Reload all scripting informations for the given division
237: *
238: * @param divisionId the division to reload
239: * @throws FxApplicationException on errors
240: */
241: public static void reloadScripting(int divisionId)
242: throws FxApplicationException {
243: long time = System.currentTimeMillis();
244: Connection con = null;
245: try {
246: try {
247: con = FxEnvironmentUtils.getDbConnection(divisionId);
248: } catch (SQLException e) {
249: LOG.error(e);
250: return;
251: }
252: FxEnvironmentImpl environment = ((FxEnvironmentImpl) CacheAdmin
253: .getEnvironment()).deepClone();
254: EnvironmentLoader loader;
255: loader = StorageManager.getEnvironmentLoader(EJBLookup
256: .getGlobalConfigurationEngine().getDivisionData(
257: divisionId));
258: environment.updateScripting(loader.loadScripts(con), loader
259: .loadScriptMapping(con, environment));
260: environment.updateTimeStamp();
261: FxEnvironmentUtils.cachePut(divisionId,
262: CacheAdmin.ENVIRONMENT_BASE,
263: CacheAdmin.ENVIRONMENT_RUNTIME, environment);
264: CacheAdmin.getEnvironment();
265: } catch (FxCacheException e) {
266: LOG.error(e, e);
267: } catch (FxNotFoundException e) {
268: throw new FxLoadException(e);
269: } finally {
270: Database.closeObjects(StructureLoader.class, con, null);
271: }
272: if (LOG.isDebugEnabled())
273: LOG.debug("Reloaded Scripting in "
274: + (System.currentTimeMillis() - time) + "[ms]");
275: }
276:
277: /**
278: * Update or add an ACL
279: *
280: * @param divisionId division
281: * @param acl the ACL to update
282: */
283: public static void updateACL(int divisionId, ACL acl) {
284: try {
285: FxEnvironmentImpl structure = ((FxEnvironmentImpl) CacheAdmin
286: .getEnvironment()).deepClone();
287: structure.updateACL(acl);
288: FxEnvironmentUtils.cachePut(divisionId,
289: CacheAdmin.ENVIRONMENT_BASE,
290: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
291: } catch (FxCacheException e) {
292: LOG.error(e, e);
293: }
294: }
295:
296: /**
297: * Remove an ACL
298: *
299: * @param divisionId division
300: * @param id ACL id
301: */
302: public static void removeACL(int divisionId, long id) {
303: try {
304: FxEnvironmentImpl structure = ((FxEnvironmentImpl) FxEnvironmentUtils
305: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
306: CacheAdmin.ENVIRONMENT_RUNTIME))
307: .deepClone();
308: structure.removeACL(id);
309: FxEnvironmentUtils.cachePut(divisionId,
310: CacheAdmin.ENVIRONMENT_BASE,
311: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
312: } catch (FxCacheException e) {
313: LOG.error(e, e);
314: }
315: }
316:
317: /**
318: * Update or add a FxType
319: *
320: * @param divisionId division
321: * @param type FxType to add/update
322: * @throws FxNotFoundException on errors
323: */
324: public static void updateType(int divisionId, FxType type)
325: throws FxNotFoundException {
326: try {
327: FxEnvironmentImpl structure = ((FxEnvironmentImpl) FxEnvironmentUtils
328: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
329: CacheAdmin.ENVIRONMENT_RUNTIME))
330: .deepClone();
331: structure.updateType(type);
332: FxEnvironmentUtils.cachePut(divisionId,
333: CacheAdmin.ENVIRONMENT_BASE,
334: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
335: } catch (FxCacheException e) {
336: LOG.error(e, e);
337: }
338: }
339:
340: /**
341: * Reload structure for an open connection (must not be called from managed beans!)
342: *
343: * @param con open and valid connection
344: * @throws FxCacheException on errors
345: * @throws FxLoadException on errors
346: */
347: public static void reload(Connection con) throws FxCacheException,
348: FxLoadException {
349: load(FxContext.get().getDivisionId(), true, con);
350: }
351:
352: /**
353: * Add a new Mandator to the environment
354: *
355: * @param divisionId division
356: * @param mandator mandator
357: */
358: public static void addMandator(int divisionId, Mandator mandator) {
359: try {
360: FxEnvironmentImpl structure = ((FxEnvironmentImpl) FxEnvironmentUtils
361: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
362: CacheAdmin.ENVIRONMENT_RUNTIME))
363: .deepClone();
364: structure.addMandator(mandator);
365: FxEnvironmentUtils.cachePut(divisionId,
366: CacheAdmin.ENVIRONMENT_BASE,
367: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
368: } catch (FxCacheException e) {
369: LOG.error(e, e);
370: }
371: }
372:
373: /**
374: * Update an existing mandator, silently fails if the mandator does not exist
375: *
376: * @param divisionId division
377: * @param mandator mandator
378: */
379: public static void updateMandator(int divisionId, Mandator mandator) {
380: try {
381: FxEnvironmentImpl structure = ((FxEnvironmentImpl) FxEnvironmentUtils
382: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
383: CacheAdmin.ENVIRONMENT_RUNTIME))
384: .deepClone();
385: structure.updateMandator(mandator);
386: FxEnvironmentUtils.cachePut(divisionId,
387: CacheAdmin.ENVIRONMENT_BASE,
388: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
389: } catch (FxCacheException e) {
390: LOG.error(e, e);
391: }
392: }
393:
394: /**
395: * Remove a mandator
396: *
397: * @param divisionId division
398: * @param mandatorId mandator
399: */
400: public static void removeMandator(int divisionId, long mandatorId) {
401: try {
402: FxEnvironmentImpl structure = ((FxEnvironmentImpl) FxEnvironmentUtils
403: .cacheGet(divisionId, CacheAdmin.ENVIRONMENT_BASE,
404: CacheAdmin.ENVIRONMENT_RUNTIME))
405: .deepClone();
406: structure.removeMandator(mandatorId);
407: FxEnvironmentUtils.cachePut(divisionId,
408: CacheAdmin.ENVIRONMENT_BASE,
409: CacheAdmin.ENVIRONMENT_RUNTIME, structure);
410: } catch (FxCacheException e) {
411: LOG.error(e, e);
412: }
413: }
414: }
|