/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.feed;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.skalli.model.Project;
import org.eclipse.skalli.services.feed.FeedEntry;
import org.eclipse.skalli.services.feed.FeedManager;
import org.eclipse.skalli.services.feed.FeedPersistenceService;
import org.eclipse.skalli.services.feed.FeedProvider;
import org.eclipse.skalli.services.feed.FeedUpdater;
import org.eclipse.skalli.services.project.ProjectService;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FeedManagerComponent implements FeedManager {
private static final Logger LOG = LoggerFactory.getLogger(FeedManagerComponent.class);
private static final String UNKNOWN_SOURCE = "unknown"; //$NON-NLS-1$
private ProjectService projectService;
private FeedPersistenceService feedPersistenceService;
private Set<FeedProvider> feedProviders = new HashSet<FeedProvider>();
private boolean doSleep = true;
public FeedManagerComponent() {
super();
}
/**
* Constructor to avoid sleeping, e.g. to speed up the test.
*/
FeedManagerComponent(boolean doSleep) {
super();
this.doSleep = doSleep;
}
protected void activate(ComponentContext context) {
LOG.info(MessageFormat.format("[FeedManager] {0} : activated",
(String) context.getProperties().get(ComponentConstants.COMPONENT_NAME)));
}
protected void deactivate(ComponentContext context) {
LOG.info(MessageFormat.format("[FeedManager] {0} : deactivated",
(String) context.getProperties().get(ComponentConstants.COMPONENT_NAME)));
}
protected void bindProjectService(ProjectService projectService) {
this.projectService = projectService;
}
protected void unbindProjectService(ProjectService projectService) {
this.projectService = null;
}
protected void bindFeedProvider(FeedProvider feedProvider) {
feedProviders.add(feedProvider);
}
protected void unbindFeedProvider(FeedProvider feedProvider) {
feedProviders.remove(feedProvider);
}
protected void bindFeedPersistenceService(FeedPersistenceService feedPersistenceService) {
this.feedPersistenceService = feedPersistenceService;
}
protected void unbindFeedPersistenceService(FeedPersistenceService feedPersistenceService) {
this.feedPersistenceService = null;
}
@Override
public void updateAllFeeds() {
if (projectService == null) {
LOG.error("Failed to update feeds since no project service is available");
return;
}
if (feedPersistenceService== null) {
LOG.warn("Failed to update feeds since no feed persistence service is available");
return;
}
LOG.info("Updating all project feeds...");
List<UUID> projectIds = new ArrayList<UUID>(projectService.keySet());
for (UUID projectId : projectIds) {
try {
Project project = projectService.getByUUID(projectId);
if (project == null) {
LOG.warn(MessageFormat.format(
"Failed to update feeds: A project with unique identifier ''{0}'' does not exist",
projectId));
return;
}
updateFeeds(project);
if (doSleep) {
try {
// delay the execution for 10 seconds, otherwise we may overload the remote systems
Thread.sleep(10000);
} catch (InterruptedException e) {
LOG.error("Feed updater job has been interrupted", e);
break;
}
}
} catch (Exception e) {
// ensure that the loop never breaks!
LOG.error(MessageFormat.format(
"Unexpected Exception: Failed to update the feed for project {0}",
projectId), e);
}
}
LOG.info("Updated all project feeds");
}
@Override
public void updateFeeds(UUID projectId) {
if (projectService == null) {
LOG.error(MessageFormat.format(
"Failed to update feeds for project {0} since no project service is available",
projectId));
return;
}
Project project = projectService.getByUUID(projectId);
if (project == null) {
LOG.warn(MessageFormat.format(
"Failed to update feeds: A project with unique identifier ''{0}'' does not exist",
projectId));
return;
}
updateFeeds(project);
}
private void updateFeeds(Project project) {
if (feedPersistenceService == null) {
LOG.warn(MessageFormat.format(
"Failed to update feeds for project {0} since no project service is available",
project.getProjectId()));
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format("updating feeds for project: {0}", project.getProjectId()));
}
for (FeedProvider feedProvider : feedProviders) {
List<FeedUpdater> feedUpdaters = feedProvider.getFeedUpdaters(project);
for (FeedUpdater feedUpdater : feedUpdaters) {
try {
List<FeedEntry> entries = feedUpdater.updateFeed(feedPersistenceService);
if (!entries.isEmpty()) {
try {
for (FeedEntry entry : entries) {
setSource(entry, feedUpdater);
entry.setProjectId(project.getUuid());
setEntryId(entry);
}
feedPersistenceService.merge(entries);
} catch (IOException e) {
LOG.error(MessageFormat.format(
"Failed to merge feed entries for project {0}",
project.getProjectId()), e);
}
}
} catch (Exception e) {
LOG.error(MessageFormat.format(
"Unexpected Exception: Failed to update the feed for project {0}",
project.getProjectId()), e);
}
}
}
}
private void setSource(FeedEntry entry, FeedUpdater feedUpdater) {
String source = entry.getSource();
if (StringUtils.isBlank(source)) {
source = feedUpdater.getSource();
if (StringUtils.isBlank(source)) {
source = UNKNOWN_SOURCE;
}
entry.setSource(source);
}
}
private void setEntryId(FeedEntry entry) {
StringBuilder newId = new StringBuilder(entry.getProjectId().toString());
Date published = entry.getPublished();
if (published != null) {
newId.append(Long.toString(published.getTime()));
}
newId.append(entry.getSource());
if (StringUtils.isNotBlank(entry.getId())) {
newId.append(entry.getId());
}
entry.setId(DigestUtils.shaHex(newId.toString()));
}
}