1 package org.exoplatform.services.wcm.extensions.scheduler.impl;
2
3 import java.lang.management.ManagementFactory;
4 import java.lang.management.RuntimeMXBean;
5 import java.text.SimpleDateFormat;
6 import java.util.Calendar;
7 import java.util.Date;
8 import java.util.HashMap;
9
10 import javax.jcr.Node;
11 import javax.jcr.NodeIterator;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.Session;
14 import javax.jcr.query.Query;
15 import javax.jcr.query.QueryManager;
16 import javax.jcr.query.QueryResult;
17
18 import org.exoplatform.services.ecm.publication.PublicationPlugin;
19 import org.exoplatform.services.ecm.publication.PublicationService;
20 import org.exoplatform.services.jcr.RepositoryService;
21 import org.exoplatform.services.jcr.core.ManageableRepository;
22 import org.exoplatform.services.jcr.ext.common.SessionProvider;
23 import org.exoplatform.services.log.ExoLogger;
24 import org.exoplatform.services.log.Log;
25 import org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.AuthoringPublicationConstant;
26 import org.exoplatform.services.wcm.publication.PublicationDefaultStates;
27 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
28 import org.quartz.Job;
29 import org.quartz.JobDataMap;
30 import org.quartz.JobExecutionContext;
31 import org.quartz.JobExecutionException;
32
33
34
35
36 public class ChangeStateCronJobImpl implements Job {
37 private static final Log LOG = ExoLogger.getLogger(ChangeStateCronJobImpl.class.getName());
38
39 private static final String START_TIME_PROPERTY = "publication:startPublishedDate";
40
41 private static final String END_TIME_PROPERTY = "publication:endPublishedDate";
42
43 private static final int NORMAL_NODE = 0;
44
45 private static final int STAGED_NODE = 1;
46
47 private String fromState = null;
48
49 private String toState = null;
50
51 private String predefinedPath = null;
52
53 private String workspace = null;
54 private String contentPath = null;
55
56
57 public void execute(JobExecutionContext context) throws JobExecutionException {
58 SessionProvider sessionProvider = null;
59 try {
60 RuntimeMXBean mx = ManagementFactory.getRuntimeMXBean();
61 if (mx.getUptime()>120000) {
62 if (LOG.isDebugEnabled()) LOG.debug("Start Execute ChangeStateCronJob");
63 if (fromState == null) {
64
65 JobDataMap jdatamap = context.getJobDetail().getJobDataMap();
66
67 fromState = jdatamap.getString("fromState");
68 toState = jdatamap.getString("toState");
69 predefinedPath = jdatamap.getString("predefinedPath");
70 String[] pathTab = predefinedPath.split(":");
71 workspace = pathTab[0];
72 contentPath = pathTab[1];
73 }
74 if (LOG.isDebugEnabled()) LOG.debug("Start Execute ChangeStateCronJob: change the State from " + fromState + " to "
75 + toState);
76
77 sessionProvider = SessionProvider.createSystemProvider();
78
79 String property = null;
80 if ("staged".equals(fromState) && "published".equals(toState)) {
81 property = START_TIME_PROPERTY;
82 } else if ("published".equals(fromState) && "unpublished".equals(toState)) {
83 property = END_TIME_PROPERTY;
84 }
85
86 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
87 Date now = Calendar.getInstance().getTime();
88 String currentTime = format.format(now);
89
90 if (property != null) {
91
92 if (contentPath != null) {
93 if (!contentPath.endsWith("/")) {
94 contentPath += "/";
95 }
96 }
97
98 StringBuilder normalNodesStatement
99 = new StringBuilder().append("select * from nt:base where ").
100 append("(publication:currentState='").append(fromState).append("') ").
101 append(" and (").append(property).append(" IS NOT NULL )").
102 append(" and (").append(property).append(" < TIMESTAMP '").append(currentTime).append("') ").
103 append(" and (jcr:path like '").append(contentPath).append("%' )");
104
105 StringBuilder stagedNodesStatement
106 = new StringBuilder().append("select * from nt:base where ").
107 append("(publication:currentState='").append(fromState).append("') ").
108 append(" and (").append(property).append(" IS NULL ) ").
109 append(" and (jcr:path like '").append(contentPath).append("%' )");
110
111 long normalCount = changeStateForNodes(sessionProvider, property, NORMAL_NODE, normalNodesStatement.toString());
112 long stagedCount = (START_TIME_PROPERTY.equals(property)) ?
113 changeStateForNodes(sessionProvider, property, STAGED_NODE, stagedNodesStatement.toString()) : 0;
114
115 long numberOfItemsToChange = normalCount + stagedCount;
116
117 if (numberOfItemsToChange > 0) {
118 if (LOG.isDebugEnabled()) {
119 LOG.debug(numberOfItemsToChange + " '" + fromState + "' candidates for state '" + toState
120 + "' found in " + predefinedPath);
121 }
122 } else {
123 if (LOG.isDebugEnabled()) {
124 LOG.debug("no '" + fromState + "' content found in " + predefinedPath);
125 }
126 }
127
128 }
129 if (LOG.isDebugEnabled()) LOG.debug("End Execute ChangeStateCronJob");
130 }
131
132 } catch (RepositoryException ex) {
133 if (LOG.isErrorEnabled()) LOG.error("Repository not found. Ignoring : " + ex.getMessage(), ex);
134 } catch (Exception ex) {
135 if (LOG.isErrorEnabled()) LOG.error("error when changing the state of the content : " + ex.getMessage(), ex);
136 } finally {
137 if (sessionProvider != null)
138 sessionProvider.close();
139 }
140 }
141
142 private long changeStateForNodes(SessionProvider sessionProvider, String property, int nodeType, String statement)
143 throws Exception {
144 long ret = 0;
145 RepositoryService repositoryService_ = WCMCoreUtils.getService(RepositoryService.class);
146 PublicationService publicationService = WCMCoreUtils.getService(PublicationService.class);
147 PublicationPlugin publicationPlugin = publicationService.getPublicationPlugins()
148 .get(AuthoringPublicationConstant.LIFECYCLE_NAME);
149 HashMap<String, String> context_ = new HashMap<String, String>();
150
151 ManageableRepository manageableRepository = repositoryService_.getCurrentRepository();
152 if (manageableRepository == null) {
153 if (LOG.isDebugEnabled()) LOG.debug("Repository not found. Ignoring");
154 return 0;
155 }
156
157 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
158
159 Session session = sessionProvider.getSession(workspace, manageableRepository);
160 QueryManager queryManager = session.getWorkspace().getQueryManager();
161
162 Query query = queryManager.createQuery(statement, Query.SQL);
163 QueryResult queryResult = query.execute();
164
165 for (NodeIterator iter = queryResult.getNodes(); iter.hasNext();) {
166 Node node_ = iter.nextNode();
167
168 String path = node_.getPath();
169 if (!path.startsWith("/jcr:system")) {
170 if (NORMAL_NODE == nodeType) {
171 Date nodeDate = node_.getProperty(property).getDate().getTime();
172 if (LOG.isInfoEnabled()) LOG.info("'" + toState + "' " + node_.getPath() + " (" + property + "="
173 + format.format(nodeDate) + ")");
174
175 if (PublicationDefaultStates.UNPUBLISHED.equals(toState)) {
176 if (node_.hasProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP)) {
177 String liveRevisionProperty = node_.getProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP)
178 .getString();
179 if (!"".equals(liveRevisionProperty)) {
180 Node liveRevision = session.getNodeByUUID(liveRevisionProperty);
181 if (liveRevision != null) {
182 context_.put(AuthoringPublicationConstant.CURRENT_REVISION_NAME,
183 liveRevision.getName());
184 }
185 }
186 }
187
188 }
189 publicationPlugin.changeState(node_, toState, context_);
190 ret ++;
191 } else {
192 if (LOG.isInfoEnabled()) LOG.info("'" + toState + "' " + node_.getPath());
193 publicationPlugin.changeState(node_, toState, context_);
194 }
195 if(START_TIME_PROPERTY.equals(property) && node_.hasProperty(START_TIME_PROPERTY)){
196 node_.getProperty(START_TIME_PROPERTY).remove();
197 node_.save();
198 }
199 if(END_TIME_PROPERTY.equals(property) && node_.hasProperty(END_TIME_PROPERTY)){
200 node_.getProperty(END_TIME_PROPERTY).remove();
201 node_.save();
202 }
203 }
204 }
205
206 return ret;
207 }
208 }