View Javadoc
1   /*
2    * Copyright (C) 2003-2008 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.services.wcm.javascript;
18  
19  import java.util.HashSet;
20  import java.util.List;
21  import java.util.Set;
22  
23  import javax.jcr.Node;
24  import javax.jcr.NodeIterator;
25  import javax.jcr.PathNotFoundException;
26  import javax.jcr.RepositoryException;
27  import javax.jcr.Session;
28  import javax.jcr.ValueFormatException;
29  import javax.jcr.query.Query;
30  import javax.jcr.query.QueryManager;
31  import javax.jcr.query.QueryResult;
32  
33  import org.apache.commons.lang.StringUtils;
34  import org.picocontainer.Startable;
35  
36  import org.exoplatform.services.cache.CacheService;
37  import org.exoplatform.services.cache.ExoCache;
38  import org.exoplatform.services.handler.SiteJavascriptHandler;
39  import org.exoplatform.services.jcr.RepositoryService;
40  import org.exoplatform.services.jcr.core.ManageableRepository;
41  import org.exoplatform.services.jcr.ext.common.SessionProvider;
42  import org.exoplatform.services.log.ExoLogger;
43  import org.exoplatform.services.log.Log;
44  import org.exoplatform.services.wcm.core.NodeLocation;
45  import org.exoplatform.services.wcm.core.NodetypeConstant;
46  import org.exoplatform.services.wcm.core.WCMConfigurationService;
47  import org.exoplatform.services.wcm.portal.LivePortalManagerService;
48  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
49  import org.exoplatform.web.application.javascript.JavascriptConfigService;
50  
51  /**
52   * Created by The eXo Platform SAS
53   * Author : Hoa.Pham
54   * hoa.pham@exoplatform.com
55   * Apr 9, 2008
56   */
57  public class XJavascriptService implements Startable {
58  
59    private static String           WEBCONTENT_JS_QUERY = "select * from exo:jsFile "
60                                                            + "where jcr:path like '{path}/%' and exo:active='true' "
61                                                            + "order by exo:priority ASC";
62  
63    /** The MODUL e_ name. */
64    final private String MODULE_NAME = "eXo.WCM.Live";
65  
66    public final static String JS_PATH_REGEXP = "/(.*)/javascript/eXo/(.*)/live";
67  
68    /** The PATH. */
69    final private String PATH = "/javascript/eXo/{portalName}/live";
70  
71    /** The js config service. */
72    private JavascriptConfigService jsConfigService ;
73  
74    /** The configuration service. */
75    private WCMConfigurationService configurationService;
76  
77    private LivePortalManagerService livePortalManagerService_;
78  
79    /** The log. */
80    private static final Log LOG = ExoLogger.getLogger(XJavascriptService.class.getName());
81  
82    private Set<String> loadedJSModule = new HashSet<String>();
83    private Set<String> loadedSharedJSModule = new HashSet<String>();
84  
85    private ExoCache<String, Object> jsCache_;
86  
87    /**
88     * Instantiates a new x javascript service.
89     *
90     * @param livePortalService the livePortal service
91     *
92     * @throws Exception the exception
93     */
94    public XJavascriptService(WCMConfigurationService wcmConfigurationService, JavascriptConfigService javascriptConfigService, LivePortalManagerService livePortalService) throws Exception{
95      this.livePortalManagerService_ = livePortalService;
96      this.jsConfigService = javascriptConfigService;
97      this.configurationService = wcmConfigurationService;
98  
99      jsCache_ = WCMCoreUtils.getService(CacheService.class).getCacheInstance(SiteJavascriptHandler.CACHE_REGION);
100 
101     this.jsConfigService.addResourceResolver(new WCMJavascriptResourceResolver(livePortalManagerService_, jsConfigService));
102   }
103 
104   /**
105    * Get active java script.
106    *
107    * @param webcontent the webcontent's node
108    * @return Code of all js file in home node.
109    * @throws Exception the exception
110    */
111   public String getActiveJavaScript(Node webcontent) throws Exception {
112     StringBuffer buffer = new StringBuffer();
113     String jsQuery = StringUtils.replaceOnce(WEBCONTENT_JS_QUERY, "{path}", webcontent.getPath());
114 
115     // Need re-login to get session because this node is get from template and the session is not live anymore.
116     NodeLocation webcontentLocation = NodeLocation.getNodeLocationByNode(webcontent);
117     RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
118     ManageableRepository repository = repositoryService.getCurrentRepository();
119     Session session = null;
120     if (webcontentLocation.getPath().startsWith("/jcr:system"))
121       session = repository.getSystemSession(repository.getConfiguration().getSystemWorkspaceName());
122     else {
123       session = repository.getSystemSession(webcontentLocation.getWorkspace());
124     }
125 
126     QueryManager queryManager = session.getWorkspace().getQueryManager();
127     Query query = queryManager.createQuery(jsQuery, Query.SQL);
128     QueryResult queryResult = query.execute();
129     NodeIterator iterator = queryResult.getNodes();
130     while(iterator.hasNext()) {
131       Node registeredJSFile = iterator.nextNode();
132       buffer.append(getActivedJSData(registeredJSFile));
133     }
134     session.logout();
135     return buffer.toString();
136   }
137 
138   /**
139    * Update and merged all Java Script in all portal when content of js file is modified.
140    *
141    * @param portalNode the portal node
142    * @param jsFile the js file
143    *
144    * @throws Exception the exception
145    */
146   public void updatePortalJSOnModify(Node portalNode, Node jsFile) throws Exception {
147     String sharedPortalName = configurationService.getSharedPortalName();
148     if(sharedPortalName.equals(portalNode.getName())) {
149       addSharedPortalJavascript(portalNode, jsFile, false);
150     }else {
151       addPortalJavascript(portalNode, jsFile, false);
152     }
153   }
154 
155   /**
156    * Update and merged all Java Script in all portal when content of js file is modified.
157    *
158    * @param portalNode the portal node
159    * @param jsFile the js file
160    *
161    * @throws Exception the exception
162    */
163   public void updatePortalJSOnRemove(Node portalNode, Node jsFile) throws Exception {
164     String sharedPortalName = configurationService.getSharedPortalName();
165     if(sharedPortalName.equals(portalNode.getName())) {
166       addSharedPortalJavascript(portalNode, jsFile, false);
167     }else {
168       addPortalJavascript(portalNode, jsFile, false);
169     }
170   }
171 
172   /**
173    * Adds the javascript.
174    *
175    * @param portalNode the portal node
176    * @param jsFile the js data
177    * @param isStartup
178    */
179   private void addPortalJavascript(Node portalNode, Node jsFile, boolean isStartup) throws Exception {
180     String javascriptPath = StringUtils.replaceOnce(PATH, "{portalName}", portalNode.getName());
181 
182     String moduleName = MODULE_NAME + '.' + portalNode.getName();
183 //    jsConfigService.invalidateCachedJScript("/" + servletContext.getServletContextName() +
184 //                                            javascriptPath);
185     if (!loadedJSModule.contains(moduleName)) {
186       loadedJSModule.add(moduleName);
187 //      jsConfigService.addPortalJScript(
188 //        new PortalJScript(moduleName, javascriptPath,"/" + servletContext.getServletContextName(),
189 //                          10, portalNode.getName()));
190     }
191     jsCache_.clearCache();
192   }
193 
194   /**
195    * Adds the javascript.
196    *
197    * @param portalNode the portal node
198    * @param jsFile the js data
199    * @param isStartup
200    */
201   private void addSharedPortalJavascript(Node portalNode, Node jsFile, boolean isStartup) throws Exception {
202     if (portalNode != null) {
203       String moduleName = MODULE_NAME + '.' + portalNode.getName();
204       if (!loadedSharedJSModule.contains(moduleName)) {
205         loadedSharedJSModule.add(moduleName);
206       }
207       jsCache_.clearCache();
208     }
209   }
210 
211   private String getActivedJSData(Node jsFile) throws ValueFormatException,
212                                           RepositoryException,
213                                           PathNotFoundException {
214     if (jsFile != null && !jsFile.isNodeType("exo:restoreLocation")
215         && jsFile.hasNode(NodetypeConstant.JCR_CONTENT)
216         && jsFile.getNode(NodetypeConstant.JCR_CONTENT).hasProperty(NodetypeConstant.JCR_DATA)
217         && jsFile.hasProperty(NodetypeConstant.EXO_ACTIVE)
218         && jsFile.getProperty(NodetypeConstant.EXO_ACTIVE).getBoolean() == true) {
219 
220       return jsFile.getNode(NodetypeConstant.JCR_CONTENT).getProperty(NodetypeConstant.JCR_DATA).getString();
221     }
222     return "";
223   }
224 
225   /* (non-Javadoc)
226    * @see org.picocontainer.Startable#start()
227    */
228   public void start() {
229     SessionProvider sessionProvider = SessionProvider.createSystemProvider();
230     try {
231       LivePortalManagerService livePortalManagerService = WCMCoreUtils.getService(LivePortalManagerService.class);
232       List<Node> livePortals = livePortalManagerService.getLivePortals(sessionProvider);
233       for(Node portal: livePortals) {
234         addPortalJavascript(portal, null, true);
235       }
236       Node sharedPortal = livePortalManagerService.getLiveSharedPortal(sessionProvider);
237       addSharedPortalJavascript(sharedPortal, null, true);
238     } catch (PathNotFoundException e) {
239       if (LOG.isWarnEnabled()) {
240         LOG.warn("Exception when merging inside Portal : WCM init is not completed.");
241       }
242     } catch (Exception e) {
243       LOG.error("Exception when start XJavascriptService", e);
244     } finally {
245       sessionProvider.close();
246     }
247   }
248 
249   /* (non-Javadoc)
250    * @see org.picocontainer.Startable#stop()
251    */
252   public void stop() {
253   }
254 
255 }