1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.scripts.impl;
18
19 import groovy.lang.GroovyClassLoader;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.File;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Set;
29
30 import javax.jcr.Node;
31 import javax.jcr.NodeIterator;
32 import javax.jcr.Property;
33 import javax.jcr.Session;
34 import javax.jcr.observation.Event;
35 import javax.jcr.observation.EventIterator;
36 import javax.jcr.observation.EventListener;
37 import javax.jcr.observation.ObservationManager;
38
39 import org.apache.commons.lang.StringUtils;
40 import org.codehaus.groovy.control.CompilationFailedException;
41 import org.exoplatform.container.ExoContainer;
42 import org.exoplatform.container.ExoContainerContext;
43 import org.exoplatform.container.component.ComponentPlugin;
44 import org.exoplatform.container.configuration.ConfigurationManager;
45 import org.exoplatform.container.xml.ObjectParameter;
46 import org.exoplatform.services.cache.CacheService;
47 import org.exoplatform.services.cms.BasePath;
48 import org.exoplatform.services.cms.impl.BaseResourceLoaderService;
49 import org.exoplatform.services.cms.impl.DMSConfiguration;
50 import org.exoplatform.services.cms.impl.DMSRepositoryConfiguration;
51 import org.exoplatform.services.cms.impl.ResourceConfig;
52 import org.exoplatform.services.cms.scripts.CmsScript;
53 import org.exoplatform.services.cms.scripts.ScriptService;
54 import org.exoplatform.services.jcr.RepositoryService;
55 import org.exoplatform.services.jcr.config.RepositoryEntry;
56 import org.exoplatform.services.jcr.core.ManageableRepository;
57 import org.exoplatform.services.jcr.ext.common.SessionProvider;
58 import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
59 import org.exoplatform.services.log.ExoLogger;
60 import org.exoplatform.services.log.Log;
61 import org.exoplatform.services.wcm.core.NodetypeConstant;
62 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
63
64 public class ScriptServiceImpl extends BaseResourceLoaderService implements ScriptService, EventListener {
65
66 private GroovyClassLoader groovyClassLoader_ ;
67 List<ScriptPlugin> plugins_ = new ArrayList<ScriptPlugin>() ;
68 private DMSConfiguration dmsConfiguration_;
69 private static final Log LOG = ExoLogger.getLogger(ScriptServiceImpl.class.getName());
70 private Set<String> configuredScripts_;
71
72
73
74
75
76
77
78
79
80
81
82 public ScriptServiceImpl(RepositoryService repositoryService, ConfigurationManager cservice,
83 NodeHierarchyCreator nodeHierarchyCreator, CacheService cacheService,
84 DMSConfiguration dmsConfiguration) throws Exception {
85 super(cservice, nodeHierarchyCreator, repositoryService, cacheService, dmsConfiguration);
86 groovyClassLoader_ = createGroovyClassLoader();
87 repositoryService_ = repositoryService ;
88 nodeHierarchyCreator_ = nodeHierarchyCreator ;
89 dmsConfiguration_ = dmsConfiguration;
90 }
91
92
93
94
95 public void start() {
96 try {
97 initPlugins();
98 } catch (Exception e) {
99 if (LOG.isErrorEnabled()) {
100 LOG.error("Unexpected error", e);
101 }
102 }
103 }
104
105
106
107
108
109
110
111 public void addScriptPlugin(ComponentPlugin plugin) {
112 if(plugin instanceof ScriptPlugin) {
113 plugins_.add((ScriptPlugin)plugin) ;
114 }
115 }
116
117
118
119
120
121
122
123
124
125
126 private void initPlugins() throws Exception{
127 configuredScripts_ = new HashSet<String>();
128 Session session = null ;
129 String scriptsPath = getBasePath();
130 for(ScriptPlugin plugin : plugins_) {
131 String scriptsLocation = plugin.getPredefineScriptsLocation();
132 if(plugin.getAutoCreateInNewRepository()) {
133 DMSRepositoryConfiguration dmsRepoConfig = null;
134 dmsRepoConfig = dmsConfiguration_.getConfig();
135 session = repositoryService_.getCurrentRepository().getSystemSession(dmsRepoConfig.getSystemWorkspace());
136 Iterator<ObjectParameter> iter = plugin.getScriptIterator() ;
137 while(iter.hasNext()) {
138 ResourceConfig resourceConfig = (ResourceConfig) iter.next().getObject();
139 init(session,resourceConfig,scriptsLocation);
140 addConfigScripts(resourceConfig);
141 }
142 ObservationManager obsManager = session.getWorkspace().getObservationManager();
143 obsManager.addEventListener(this, Event.PROPERTY_CHANGED, scriptsPath, true, null, null, true);
144 session.save();
145 session.logout();
146 }
147 ManageableRepository mRepository = repositoryService_.getCurrentRepository();
148 DMSRepositoryConfiguration dmsDefaultRepoConfig = dmsConfiguration_.getConfig();
149 session = mRepository.getSystemSession(dmsDefaultRepoConfig.getSystemWorkspace()) ;
150 Iterator<ObjectParameter> iter = plugin.getScriptIterator() ;
151 while(iter.hasNext()) {
152 init(session,(ResourceConfig) iter.next().getObject(),scriptsLocation) ;
153 }
154 ObservationManager obsManager = session.getWorkspace().getObservationManager();
155 obsManager.addEventListener(this, Event.PROPERTY_CHANGED, scriptsPath, true, null, null, true);
156 session.save();
157 session.logout();
158 }
159 }
160
161
162
163
164
165
166 protected String getBasePath() { return nodeHierarchyCreator_.getJcrPath(BasePath.CMS_SCRIPTS_PATH); }
167
168
169
170
171 public void initRepo() throws Exception {
172 configuredScripts_ = new HashSet<String>();
173 ManageableRepository mRepository = repositoryService_.getCurrentRepository();
174 String scriptsPath = getBasePath();
175 DMSRepositoryConfiguration dmsRepoConfig = dmsConfiguration_.getConfig();
176 Session session = mRepository.getSystemSession(dmsRepoConfig.getSystemWorkspace()) ;
177 for(ScriptPlugin plugin : plugins_) {
178 if(!plugin.getAutoCreateInNewRepository()) continue ;
179 String scriptsLocation = plugin.getPredefineScriptsLocation();
180 Iterator<ObjectParameter> iter = plugin.getScriptIterator() ;
181 while(iter.hasNext()) {
182 ResourceConfig resourceConfig = (ResourceConfig) iter.next().getObject();
183 init(session, resourceConfig,scriptsLocation);
184 addConfigScripts(resourceConfig);
185 }
186 ObservationManager obsManager = session.getWorkspace().getObservationManager();
187 obsManager.addEventListener(this, Event.PROPERTY_CHANGED, scriptsPath, true, null, null, true);
188
189 }
190 session.save();
191 session.logout();
192 }
193
194
195
196
197 public Node getECMScriptHome(SessionProvider provider) throws Exception {
198 Session session = getSession(provider);
199 return getNodeByAlias(BasePath.ECM_EXPLORER_SCRIPTS,session);
200 }
201
202
203
204
205 @Override
206 public List<Node> getECMActionScripts(SessionProvider provider) throws Exception {
207 Session session = getSession(provider);
208 return getScriptList(BasePath.ECM_ACTION_SCRIPTS, session);
209 }
210
211
212
213
214 @Override
215 public List<Node> getECMInterceptorScripts(SessionProvider provider) throws Exception {
216 Session session = getSession(provider);
217 return getScriptList(BasePath.ECM_INTERCEPTOR_SCRIPTS, session);
218 }
219
220
221
222
223 @Override
224 public List<Node> getECMWidgetScripts(SessionProvider provider) throws Exception {
225 Session session = getSession(provider);
226 return getScriptList(BasePath.ECM_WIDGET_SCRIPTS,session);
227 }
228
229
230
231
232 @Override
233 public String getBaseScriptPath() throws Exception {
234 return getBasePath() ;
235 }
236
237
238
239
240 @Override
241 public String getScriptAsText(Node script) throws Exception {
242 return script.getNode(NodetypeConstant.JCR_CONTENT).getProperty(NodetypeConstant.JCR_DATA).getString();
243 }
244
245
246
247
248 @Override
249 public synchronized CmsScript getScript(String scriptName) throws Exception {
250 CmsScript scriptObject = resourceCache_.get(scriptName);
251 if (scriptObject != null) return scriptObject;
252 ExoContainer container = ExoContainerContext.getCurrentContainer() ;
253 try {
254 scriptObject = (CmsScript) container.getComponentInstance(scriptName);
255 if(scriptObject !=null ) {
256 resourceCache_.put(scriptName, scriptObject) ;
257 return scriptObject;
258 }
259 } catch (NoClassDefFoundError e) {
260 if (LOG.isWarnEnabled()) {
261 LOG.warn(e.getMessage());
262 }
263 }
264
265 groovyClassLoader_ = createGroovyClassLoader();
266 Class scriptClass = groovyClassLoader_.loadClass(scriptName) ;
267 container.registerComponentImplementation(scriptName, scriptClass);
268 scriptObject = (CmsScript) container.getComponentInstance(scriptName);
269 resourceCache_.put(scriptName, scriptObject) ;
270
271 return scriptObject;
272 }
273
274
275
276
277 @Override
278 public void addScript(String name, String text, SessionProvider provider) throws Exception {
279 addScript(name, name, text, provider);
280 }
281
282
283
284
285 @Override
286 public void addScript(String name, String description, String text, SessionProvider provider) throws Exception {
287 Node resourcesHome = getResourcesHome(provider);
288 InputStream in = new ByteArrayInputStream(text.getBytes());
289 addResource(resourcesHome, name, description, in);
290 removeFromCache(name) ;
291 }
292
293
294
295
296 @Override
297 public void removeScript(String scriptName, SessionProvider provider) throws Exception {
298 removeResource(scriptName, provider);
299 removeFromCache(scriptName) ;
300 }
301
302
303
304
305
306
307
308
309
310
311 private Node getScriptHome(String scriptAlias, Session session) throws Exception {
312 String path = nodeHierarchyCreator_.getJcrPath(scriptAlias) ;
313 return (Node)session.getItem(path);
314 }
315
316
317
318
319
320
321
322
323
324
325 private List<Node> getScriptList(String scriptAlias,Session session) throws Exception {
326 List<Node> scriptList = new ArrayList<Node>() ;
327 Node scriptHome = getScriptHome(scriptAlias,session) ;
328 for(NodeIterator iter = scriptHome.getNodes(); iter.hasNext() ;) {
329 scriptList.add(iter.nextNode()) ;
330 }
331 return scriptList;
332 }
333
334
335
336
337
338
339
340
341 @Override
342 protected void removeFromCache(String scriptName){
343 try{
344 Object cachedobject = resourceCache_.get(scriptName);
345 if (cachedobject != null) {
346 resourceCache_.remove(scriptName) ;
347 ExoContainer container = ExoContainerContext.getCurrentContainer();
348 container.unregisterComponent(scriptName);
349 }
350 } catch (Exception e) {
351 if (LOG.isWarnEnabled()) {
352 LOG.warn(e.getMessage());
353 }
354 }
355 }
356
357
358
359
360
361
362
363
364 @Override
365 public void onEvent(EventIterator events) {
366 while (events.hasNext()) {
367 Event event = events.nextEvent();
368 String path = null;
369 Session jcrSession = null ;
370 try {
371 path = event.getPath();
372 DMSRepositoryConfiguration dmsRepoConfig = null;
373 try {
374 ManageableRepository manageableRepository = repositoryService_.getCurrentRepository();
375 dmsRepoConfig = dmsConfiguration_.getConfig();
376 jcrSession = manageableRepository.getSystemSession(dmsRepoConfig.getSystemWorkspace());
377 Property property = (Property) jcrSession.getItem(path);
378 if ("jcr:data".equals(property.getName())) {
379 Node node = property.getParent().getParent();
380 removeFromCache(StringUtils.removeStart(StringUtils.removeStart(node.getPath(), this.getBaseScriptPath()), "/"));
381 }
382 jcrSession.logout();
383 } catch (Exception e) {
384 jcrSession.logout();
385 continue ;
386 }
387 } catch (Exception e) {
388 if (LOG.isErrorEnabled()) {
389 LOG.error("Unexpected error", e);
390 }
391 }
392 }
393 }
394
395
396
397
398
399
400 private GroovyClassLoader createGroovyClassLoader() {
401 ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
402 return new GroovyClassLoader(parentLoader) {
403 @SuppressWarnings("unchecked")
404 protected Class findClass(String className) throws ClassNotFoundException {
405 String filename = null ;
406 String nodeName = null ;
407 if(className.indexOf(":") > -1) {
408 String[] array = className.split(":") ;
409 nodeName = array[1] ;
410 filename = array[1].replace('.', File.separatorChar) + ".groovy";
411 }else {
412 nodeName = className ;
413 filename = className.replace('.', File.separatorChar) + ".groovy";
414 }
415 String scriptContent = null;
416 try {
417 scriptContent = WCMCoreUtils.getService(BaseResourceLoaderService.class).getResourceAsText(nodeName);
418 } catch (Exception e) {
419 throw new ClassNotFoundException("Could not read " + nodeName + ": " + e);
420 }
421 try {
422 return parseClass(scriptContent, filename);
423 } catch (CompilationFailedException e2) {
424 throw new ClassNotFoundException("Syntax error in " + filename
425 + ": " + e2);
426 }
427 }
428 };
429 }
430
431
432
433
434 @Override
435 public Node getScriptNode(String scriptName,SessionProvider provider) throws Exception {
436 try {
437 Node scriptHome = getResourcesHome(provider) ;
438 return scriptHome.getNode(scriptName) ;
439 }catch (Exception e) {
440 return null;
441 }
442 }
443
444
445
446
447
448
449
450
451
452
453
454 private Session getSession(SessionProvider provider) throws Exception {
455 ManageableRepository manageableRepository = repositoryService_.getCurrentRepository();
456 DMSRepositoryConfiguration dmsRepoConfig = dmsConfiguration_.getConfig();
457 return provider.getSession(dmsRepoConfig.getSystemWorkspace(), manageableRepository);
458 }
459
460
461
462
463
464
465
466
467
468
469
470 private Node getNodeByAlias(String alias,Session session) throws Exception {
471 String path = nodeHierarchyCreator_.getJcrPath(alias) ;
472 return (Node)session.getItem(path);
473 }
474
475
476
477
478 @Override
479 public Set<String> getAllConfiguredScripts() {
480 return configuredScripts_;
481 }
482
483 private void addConfigScripts(ResourceConfig resourceConfig) {
484 for (Object obj : resourceConfig.getRessources()) {
485 if (obj instanceof ResourceConfig.Resource) {
486 ResourceConfig.Resource resource = (ResourceConfig.Resource)obj;
487 String name = resource.getName();
488 if (name.indexOf("/") >=0 ) {
489 name = name.substring(name.lastIndexOf("/") + 1);
490 }
491 configuredScripts_.add(name);
492 }
493 }
494 }
495
496 }