1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.wcm.link;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.List;
22
23 import javax.jcr.Node;
24 import javax.jcr.NodeIterator;
25 import javax.jcr.Property;
26 import javax.jcr.Session;
27 import javax.jcr.Value;
28 import javax.jcr.ValueFactory;
29 import javax.jcr.query.Query;
30 import javax.jcr.query.QueryManager;
31 import javax.jcr.query.QueryResult;
32
33 import org.apache.commons.httpclient.HttpClient;
34 import org.apache.commons.httpclient.SimpleHttpConnectionManager;
35 import org.apache.commons.httpclient.methods.GetMethod;
36 import org.exoplatform.container.xml.InitParams;
37 import org.exoplatform.container.xml.PropertiesParam;
38 import org.exoplatform.services.cache.CacheService;
39 import org.exoplatform.services.cache.ExoCache;
40 import org.exoplatform.services.jcr.RepositoryService;
41 import org.exoplatform.services.jcr.core.ManageableRepository;
42 import org.exoplatform.services.jcr.ext.common.SessionProvider;
43 import org.exoplatform.services.log.ExoLogger;
44 import org.exoplatform.services.log.Log;
45 import org.exoplatform.services.wcm.core.NodeLocation;
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
50
51
52
53
54 public class LiveLinkManagerServiceImpl implements LiveLinkManagerService {
55
56
57 private ExoCache<String, List<String>> brokenLinksCache;
58
59
60 private WCMConfigurationService configurationService;
61
62
63 private RepositoryService repositoryService;
64
65
66 private LivePortalManagerService livePortalManagerService;
67
68
69 private String internalServerPath;
70
71
72 final private static Log LOG = ExoLogger.getLogger(LiveLinkManagerServiceImpl.class.getName());
73
74 private final static String CACHE_NAME = "ecms.LiveLinkManagerService";
75
76
77
78
79
80
81
82
83
84
85
86
87 public LiveLinkManagerServiceImpl(
88 WCMConfigurationService configurationService,
89 RepositoryService repositoryService,
90 LivePortalManagerService livePortalManagerService,
91 CacheService cacheService,
92 InitParams initParams) throws Exception {
93 this.configurationService = configurationService;
94 this.repositoryService = repositoryService;
95 this.livePortalManagerService = livePortalManagerService;
96 this.brokenLinksCache = cacheService.getCacheInstance(CACHE_NAME);
97
98 PropertiesParam propertiesParam = initParams.getPropertiesParam("server.config");
99 String scheme = propertiesParam.getProperty("scheme");
100 String hostName = propertiesParam.getProperty("hostName");
101 String port = propertiesParam.getProperty("port");
102 StringBuilder builder = new StringBuilder();
103 builder.append(scheme).append("://").append(hostName).append(":").append(port);
104 internalServerPath = builder.toString();
105 }
106
107
108
109
110 public List<LinkBean> getBrokenLinks(String portalName) throws Exception {
111 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
112 Node portal = livePortalManagerService.getLivePortal(sessionProvider, portalName);
113 String path = portal.getPath();
114 Session session = portal.getSession();
115 List<LinkBean> listBrokenLinks = new ArrayList<LinkBean>();
116 QueryManager queryManager = session.getWorkspace().getQueryManager();
117 Query query = queryManager.createQuery("select * from exo:webContent where jcr:path like '" + path + "/%'", Query.SQL);
118 QueryResult results = query.execute();
119 NodeIterator iter = results.getNodes();
120 for (;iter.hasNext();) {
121 Node webContent = iter.nextNode();
122 List<String> listBrokenUrls = getBrokenLinks(webContent);
123 for (String brokenUrl : listBrokenUrls) {
124 LinkBean linkBean = new LinkBean(brokenUrl, LinkBean.STATUS_BROKEN);
125 listBrokenLinks.add(linkBean);
126 }
127 }
128 return listBrokenLinks;
129 }
130
131
132
133
134 public List<String> getBrokenLinks(Node webContent) throws Exception {
135 List<String> listBrokenUrls = (List<String>) brokenLinksCache.get(webContent.getUUID());
136 if (listBrokenUrls == null || listBrokenUrls.size() == 0) {
137 listBrokenUrls = new ArrayList<String>();
138 if (webContent.hasProperty("exo:links")) {
139 for (Value value : webContent.getProperty("exo:links").getValues()) {
140 String link = value.getString();
141 LinkBean linkBean = LinkBean.parse(link);
142 if (linkBean.isBroken()) {
143 listBrokenUrls.add(linkBean.getUrl());
144 }
145 }
146 brokenLinksCache.put(webContent.getUUID(), listBrokenUrls);
147 }
148 }
149 return listBrokenUrls;
150 }
151
152
153
154
155 public void updateLinks() throws Exception {
156 try {
157 Collection<NodeLocation> nodeLocationCollection = configurationService.getAllLivePortalsLocation();
158 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
159 Session session = null;
160 for (NodeLocation nodeLocation : nodeLocationCollection) {
161 String workspace = nodeLocation.getWorkspace();
162 String path = nodeLocation.getPath();
163 ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
164 session = sessionProvider.getSession(workspace, manageableRepository);
165 updateLinkStatus(session, "select * from exo:linkable where jcr:path like '" + path + "/%'");
166 }
167 } catch (Exception e) {
168 if (LOG.isErrorEnabled()) {
169 LOG.error("Error when perform updateLinks: ", e);
170 }
171 }
172 }
173
174
175
176
177 public void updateLinks(String portalName) throws Exception {
178 try {
179 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
180 Node portal = livePortalManagerService.getLivePortal(sessionProvider, portalName);
181 String path = portal.getPath();
182 Session session = portal.getSession();
183 updateLinkStatus(session, "select * from exo:linkable where jcr:path like '" + path + "/%'");
184 } catch (Exception e) {
185 if (LOG.isErrorEnabled()) {
186 LOG.error("Error when perform updateLinks: ", e);
187 }
188 }
189 }
190
191
192
193
194
195
196
197
198
199 private void updateLinkStatus(Session session, String queryCommand) throws Exception{
200 List<String> listBrokenLinks = new ArrayList<String>();
201 ValueFactory valueFactory = session.getValueFactory();
202 QueryManager queryManager = session.getWorkspace().getQueryManager();
203 Query query = queryManager.createQuery(queryCommand, Query.SQL);
204 QueryResult results = query.execute();
205 NodeIterator iter = results.getNodes();
206 for (; iter.hasNext();) {
207 Node webContent = iter.nextNode();
208 if (!webContent.isCheckedOut() || webContent.isLocked()
209 || (webContent.isCheckedOut() && !webContent.getParent().isCheckedOut())) {
210 continue;
211 }
212 Property links = webContent.getProperty("exo:links");
213 Value[] oldValues = links.getValues();
214 Value[] newValues = new Value[oldValues.length];
215 for (int iValues = 0; iValues < oldValues.length; iValues++) {
216 String oldLink = oldValues[iValues].getString();
217 if (!oldLink.equals("")) {
218 LinkBean linkBean = LinkBean.parse(oldLink);
219 String oldUrl = linkBean.getUrl();
220 String oldStatus = getLinkStatus(oldUrl);
221 String updatedLink = new LinkBean(oldUrl, oldStatus).toString();
222 if (LOG.isInfoEnabled()) {
223 LOG.info(updatedLink);
224 }
225 newValues[iValues] = valueFactory.createValue(updatedLink);
226 if (oldStatus.equals(LinkBean.STATUS_BROKEN)) {
227 listBrokenLinks.add(oldUrl);
228 }
229 }
230 }
231 webContent.setProperty("exo:links",newValues);
232 brokenLinksCache.put(webContent.getUUID(), listBrokenLinks);
233 }
234 session.save();
235 }
236
237
238
239
240
241
242
243
244 private String getLinkStatus(String strUrl) {
245 try {
246 String fullUrl = strUrl;
247 if(strUrl.startsWith("/")) {
248 fullUrl = internalServerPath + strUrl;
249 }
250 fullUrl = fullUrl.replaceAll(" ","%20");
251 HttpClient httpClient = new HttpClient(new SimpleHttpConnectionManager());
252 GetMethod getMethod = new GetMethod(fullUrl);
253 if(httpClient.executeMethod(getMethod) == 200) {
254 return LinkBean.STATUS_ACTIVE;
255 }
256 return LinkBean.STATUS_BROKEN;
257 } catch (Exception e) {
258 if (LOG.isInfoEnabled()) {
259 LOG.info("URL Link: \"" + strUrl + "\" is broken");
260 }
261 return LinkBean.STATUS_BROKEN;
262 }
263 }
264
265
266
267
268 public List<String> extractLinks(Node htmlFile) throws Exception {
269 String htmlData = htmlFile.getNode("jcr:content").getProperty("jcr:data").getString();
270 List<String> listHyperlink = new ArrayList<String>();
271 HTMLLinkExtractor htmlLinkExtractor = new HTMLLinkExtractor();
272 List<HTMLLinkExtractor.HtmlLink> htmlLinks = htmlLinkExtractor.grabHTMLLinks(htmlData);
273 for (HTMLLinkExtractor.HtmlLink link : htmlLinks) {
274 if (!listHyperlink.contains(link.toString()))
275 listHyperlink.add(link.toString());
276 }
277 return listHyperlink;
278 }
279
280
281
282
283
284 public void updateLinkDataForNode(Node webContent, List<String> newLinks) throws Exception {
285 ValueFactory valueFactory = webContent.getSession().getValueFactory();
286 if (webContent.canAddMixin("exo:linkable")) {
287 webContent.addMixin("exo:linkable");
288 }
289
290 List<String> listExtractedLink = new ArrayList<String>();
291 if (webContent.hasProperty("exo:links")) {
292 Property property = webContent.getProperty("exo:links");
293 for (Value value : property.getValues()) {
294 listExtractedLink.add(value.getString());
295 }
296 }
297
298 List<String> listResult = new ArrayList<String>();
299
300 for (String extractedLink : listExtractedLink) {
301 for (String newUrl : newLinks) {
302 if (LinkBean.parse(extractedLink).getUrl().equals(newUrl)) {
303 listResult.add(extractedLink);
304 }
305 }
306 }
307 List<String> listTemp = new ArrayList<String>();
308 listTemp.addAll(newLinks);
309
310 for (String newUrl : newLinks) {
311 for (String extractedLink : listExtractedLink) {
312 if (newUrl.equals(LinkBean.parse(extractedLink).getUrl())) {
313 listTemp.set(newLinks.indexOf(newUrl), "");
314 }
315 }
316 }
317
318 for (String strTemp : listTemp) {
319 if (!strTemp.equals("")) {
320 listResult.add(strTemp);
321 }
322 }
323
324
325 Value[] values = new Value[listResult.size()];
326 for(String url: listResult) {
327 if (url.indexOf(LinkBean.STATUS) < 0) {
328 LinkBean linkBean = new LinkBean(url, LinkBean.STATUS_UNCHECKED);
329 values[listResult.indexOf(url)] = valueFactory.createValue(linkBean.toString());
330 } else {
331 values[listResult.indexOf(url)] = valueFactory.createValue(url);
332 }
333 }
334 webContent.setProperty("exo:links", values);
335 webContent.save();
336 }
337
338 }