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.shared;
034:
035: import com.flexive.shared.cache.FxCacheException;
036: import com.flexive.shared.configuration.*;
037: import com.flexive.shared.content.FxCachedContent;
038: import com.flexive.shared.content.FxCachedContentContainer;
039: import com.flexive.shared.content.FxPK;
040: import com.flexive.shared.exceptions.FxApplicationException;
041: import com.flexive.shared.exceptions.FxLoadException;
042: import com.flexive.shared.exceptions.FxNoAccessException;
043: import com.flexive.shared.mbeans.FxCacheMBean;
044: import com.flexive.shared.mbeans.FxCacheProxy;
045: import com.flexive.shared.mbeans.MBeanHelper;
046: import com.flexive.shared.structure.FxFilteredEnvironment;
047: import com.flexive.shared.structure.FxEnvironment;
048: import com.flexive.stream.ServerLocation;
049: import org.apache.commons.logging.Log;
050: import org.apache.commons.logging.LogFactory;
051:
052: import javax.management.MBeanServer;
053: import java.util.List;
054:
055: /**
056: * FxCache access
057: *
058: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
059: */
060: public class CacheAdmin {
061: private static transient Log LOG = LogFactory
062: .getLog(CacheAdmin.class);
063:
064: public final static String ROOT_USERTICKETSTORE = "/UserTicketStore";
065: public final static String ROOT_WEBDAV_USERTICKETSTORE = "/WebdavUserTicketStore";
066: public final static String CACHE_SERVICE_NAME = "flexive:service=FxCache";
067: public final static String LANGUAGES_ID = "/FxLang/Id";
068: public final static String LANGUAGES_ISO = "/FxLang/ISO";
069: public final static String LANGUAGES_ALL = "/FxLang/ISO";
070: public final static String ENVIRONMENT_BASE = "/FxEnvironment";
071: public static final Object ENVIRONMENT_RUNTIME = "runtime";
072: public final static String STREAMSERVER_BASE = "/FxStreamServers";
073: public final static String STREAMSERVER_EJB_KEY = "ejb_servers";
074: public final static String CONTENTCACHE_BASE = "/FxContent";
075:
076: private static final Parameter<Boolean> DROP_RUNONCE = ParameterFactory
077: .newInstance(Boolean.class, "/cacheAdmin/dropInRunOnce",
078: ParameterScope.DIVISION_ONLY, false);
079:
080: // "cached" cache beans
081: private static FxCacheMBean cache = null;
082:
083: // private static ThreadLocal<FxEnvironment> requestEnvironment = new ThreadLocal<FxEnvironment>();
084:
085: /**
086: * Returns the FxCache instance.
087: *
088: * @return the cache instance
089: */
090: public static synchronized FxCacheMBean getInstance() {
091: if (cache != null) {
092: return cache;
093: }
094: // System.out.println("Locating ....");
095:
096: try {
097: MBeanServer server = MBeanHelper.locateServer();
098: cache = new FxCacheProxy(server);
099: if (!server.isRegistered(((FxCacheProxy) cache).getName())) {
100: LOG.info("Registering FxCacheMBean .... ");
101: EJBLookup.getGlobalConfigurationEngine()
102: .registerCacheMBean(
103: ((FxCacheProxy) cache).getName());
104: // server.registerMBean(new FxCache(), ((FxCacheProxy)cache).getName());
105: if (LOG.isDebugEnabled())
106: LOG
107: .debug("Registered: "
108: + server
109: .isRegistered(((FxCacheProxy) cache)
110: .getName()));
111: cache.create();
112: } else {
113: //check if MBean Server is from current deployment
114: String deployedId = cache.getDeploymentId();
115: if (MBeanHelper.DEPLOYMENT_ID.equals(deployedId))
116: return cache;
117: LOG.info("Redeployment! Have to undeploy " + deployedId
118: + " (vs " + MBeanHelper.DEPLOYMENT_ID + ")");
119: cache.destroy();
120: // System.out.println("Unregistering ...");
121: server
122: .unregisterMBean(((FxCacheProxy) cache)
123: .getName());
124: // System.out.println("Registering new ...");
125: EJBLookup.getGlobalConfigurationEngine()
126: .registerCacheMBean(
127: ((FxCacheProxy) cache).getName());
128: // server.registerMBean(new FxCache(), ((FxCacheProxy)cache).getName());
129: LOG.debug("Registered: "
130: + server.isRegistered(((FxCacheProxy) cache)
131: .getName()));
132: cache.create();
133: }
134: /* MBeanServer server = MBeanServerLocator.locate();
135: cache = (FxCacheMBean) MBeanProxyExt.create(
136: FxCacheMBean.class,
137: CACHE_SERVICE_NAME,
138: server);*/
139: return cache;
140: } catch (Exception e) {
141: LOG.error(e.getMessage(), e);
142: return null;
143: }
144: }
145:
146: /**
147: * Is this a new and uninitialized flexive installation?
148: * Useful to display splashscreens etc.
149: *
150: * @return if this is a new flexive installation
151: */
152: public static boolean isNewInstallation() {
153: try {
154: return getInstance().get(ENVIRONMENT_BASE,
155: ENVIRONMENT_RUNTIME) == null
156: && !EJBLookup.getDivisionConfigurationEngine().get(
157: SystemParameters.DIVISION_RUNONCE);
158: } catch (FxCacheException e) {
159: throw new RuntimeException(e.getMessage(), e);
160: } catch (FxApplicationException e) {
161: throw e.asRuntimeException();
162: }
163: }
164:
165: /**
166: * Has the environment been loaded (yet) - internal helper
167: *
168: * @return if the environment has been loaded yet
169: */
170: public static boolean isEnvironmentLoaded() {
171: try {
172: return getInstance().get(ENVIRONMENT_BASE,
173: ENVIRONMENT_RUNTIME) != null;
174: } catch (FxCacheException e) {
175: return false;
176: }
177: }
178:
179: /**
180: * Get the FxEnvironment runtime from the cache
181: *
182: * @return FxEnvironment
183: */
184: public static synchronized FxEnvironment getEnvironment() {
185: try {
186: // if (requestEnvironment.get() != null) {
187: // return requestEnvironment.get();
188: // }
189: FxEnvironment ret = (FxEnvironment) getInstance().get(
190: ENVIRONMENT_BASE, ENVIRONMENT_RUNTIME);
191: if (ret == null) {
192: FxContext ri = FxContext.get();
193: if (!DivisionData.isValidDivisionId(ri.getDivisionId())) {
194: throw new FxCacheException(
195: "Division Id missing in request information");
196: }
197: getInstance().reloadEnvironment(ri.getDivisionId());
198: if (!EJBLookup.getTimerService().isInstalled()) {
199: EJBLookup.getTimerService().install();
200: }
201: //execute run-once scripts
202: EJBLookup.getScriptingEngine().executeRunOnceScripts();
203: //execute startup scripts
204: EJBLookup.getScriptingEngine().executeStartupScripts();
205:
206: for (String dropName : FxSharedUtils.getDrops()) {
207: // set the drop name as key on the DROP_RUNONCE parameter
208: final Parameter<Boolean> dropParameter = DROP_RUNONCE
209: .copy().setData(
210: new ParameterDataEditBean<Boolean>(
211: DROP_RUNONCE.getData())
212: .setKey(dropName));
213: EJBLookup.getScriptingEngine()
214: .executeDropRunOnceScripts(dropParameter,
215: dropName);
216:
217: // also run startup-scripts now
218: EJBLookup.getScriptingEngine()
219: .executeDropStartupScripts(dropName);
220: }
221: //Create eviction strategy if supported
222: cache.setEvictionStrategy(ri.getDivisionId(),
223: CONTENTCACHE_BASE, 5000, 0, 120);
224:
225: // make sure we don't miss any updates in the environment
226: getInstance().reloadEnvironment(ri.getDivisionId());
227: ret = (FxEnvironment) getInstance().get(
228: ENVIRONMENT_BASE, ENVIRONMENT_RUNTIME);
229: if (ret == null)
230: throw new FxLoadException(
231: "ex.structure.runtime.cache.notFound");
232: }
233: // requestEnvironment.set(ret);
234: return ret;
235: } catch (FxCacheException e) {
236: throw new FxLoadException(LOG, e, "ex.cache.access.error",
237: e.getMessage()).asRuntimeException();
238: } catch (FxLoadException f) {
239: throw f.asRuntimeException(); //pass thru
240: } catch (Exception e) {
241: e.printStackTrace();
242: throw new FxLoadException(LOG, e, "ex.cache.access.error",
243: e.getClass().getName() + ": " + e.getMessage())
244: .asRuntimeException();
245: }
246: }
247:
248: /**
249: * Return a {@link com.flexive.shared.structure.FxFilteredEnvironment} for the calling user.
250: *
251: * @return a {@link com.flexive.shared.structure.FxFilteredEnvironment} for the calling user.
252: */
253: public static FxEnvironment getFilteredEnvironment() {
254: return new FxFilteredEnvironment(getEnvironment());
255: }
256:
257: /**
258: * Force reloading of the environment for the current division. May only
259: * be called by the supervisor user.
260: *
261: * @throws Exception on errors
262: */
263: public static void reloadEnvironment() throws Exception {
264: if (!FxContext.get().getTicket().isGlobalSupervisor()) {
265: throw new FxNoAccessException("ex.cache.reload.privileges")
266: .asRuntimeException();
267: }
268: getInstance()
269: .reloadEnvironment(FxContext.get().getDivisionId());
270: // requestEnvironment.set(null);
271: }
272:
273: /**
274: * Put a content and its security info in the cache
275: *
276: * @param content the content to cache
277: */
278: public static void cacheContent(FxCachedContent content) {
279: try {
280: FxCachedContentContainer container = (FxCachedContentContainer) getInstance()
281: .get(CONTENTCACHE_BASE,
282: content.getContent().getId());
283: if (container == null) {
284: container = new FxCachedContentContainer(content);
285: } else {
286: container.add(content);
287: }
288: getInstance().put(CONTENTCACHE_BASE, container.getId(),
289: container);
290: } catch (FxCacheException e) {
291: LOG.warn(e.getMessage(), e);
292: }
293: }
294:
295: /**
296: * Try to obtain a cached copy of a content identified by its primary key, will return <code>null</code> if not cached
297: *
298: * @param pk requested primary key
299: * @return the cached content or <code>null</code> if not found
300: */
301: public static FxCachedContent getCachedContent(FxPK pk) {
302: try {
303: FxCachedContentContainer container = (FxCachedContentContainer) getInstance()
304: .get(CONTENTCACHE_BASE, pk.getId());
305: if (container != null)
306: return container.get(pk);
307: return null;
308: } catch (FxCacheException e) {
309: LOG.warn(e.getMessage(), e);
310: return null;
311: }
312: }
313:
314: /**
315: * Expire all cached versions of a content with the requested id
316: *
317: * @param id requested id
318: */
319: public static void expireCachedContent(long id) {
320: if (id <= 0)
321: return;
322: try {
323: getInstance().remove(CONTENTCACHE_BASE, id);
324: } catch (FxCacheException e) {
325: LOG.warn(e.getMessage(), e);
326: }
327: }
328:
329: /**
330: * Expire all cached contents
331: */
332: public static void expireCachedContents() {
333: try {
334: getInstance().remove(CONTENTCACHE_BASE);
335: } catch (FxCacheException e) {
336: LOG.warn(e.getMessage(), e);
337: }
338: }
339:
340: /**
341: * Called from external methods when the environment changed.
342: */
343: public static void environmentChanged() {
344: // requestEnvironment.set(null);
345: }
346:
347: /**
348: * Get a list of all available StreamServers
349: *
350: * @return list of all available StreamServers
351: */
352: @SuppressWarnings("unchecked")
353: public static List<ServerLocation> getStreamServers() {
354: try {
355: List<ServerLocation> ret = (List<ServerLocation>) getInstance()
356: .globalGet(STREAMSERVER_BASE, STREAMSERVER_EJB_KEY);
357: if (ret == null)
358: throw new FxLoadException(
359: "ex.cache.streamservers.notFound");
360: return ret;
361: } catch (FxCacheException e) {
362: throw new FxLoadException(LOG, e, "ex.cache.access.error",
363: e.getMessage()).asRuntimeException();
364: } catch (FxLoadException f) {
365: throw f.asRuntimeException(); //pass thru
366: } catch (Exception e) {
367: throw new FxLoadException(LOG, e, "ex.cache.access.error",
368: e.getClass().getName(), e.getMessage())
369: .asRuntimeException();
370: }
371: }
372:
373: }
|