You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nutch.apache.org by le...@apache.org on 2014/09/22 16:18:55 UTC

svn commit: r1626786 [3/3] - in /nutch/branches/2.x: ./ ivy/ src/bin/ src/java/org/apache/nutch/api/ src/java/org/apache/nutch/api/impl/ src/java/org/apache/nutch/api/model/request/ src/java/org/apache/nutch/api/resources/ src/java/org/apache/nutch/web...

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/seed/SeedPage.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/seed/SeedPage.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/seed/SeedPage.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/seed/SeedPage.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,152 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.pages.seed;
+
+import java.util.Iterator;
+
+import org.apache.nutch.webui.model.SeedList;
+import org.apache.nutch.webui.model.SeedUrl;
+import org.apache.nutch.webui.pages.AbstractBasePage;
+import org.apache.nutch.webui.pages.components.CpmIteratorAdapter;
+import org.apache.nutch.webui.service.SeedListService;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.RefreshingView;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+import com.google.common.collect.Lists;
+
+/**
+ * This page is for seed urls management
+ * 
+ * @author feodor
+ * 
+ */
+public class SeedPage extends AbstractBasePage<SeedList> {
+
+  @SpringBean
+  private SeedListService seedListService;
+
+  private Form<SeedUrl> urlForm;
+
+  private WebMarkupContainer seedUrlsTable;
+
+  public SeedPage() {
+    SeedList list = new SeedList();
+    list.setSeedUrls(Lists.<SeedUrl> newArrayList());
+    initPage(Model.of(list));
+  }
+
+  public SeedPage(final PageParameters parameters) {
+    initPage(new LoadableDetachableModel<SeedList>() {
+
+      @Override
+      protected SeedList load() {
+        Long seedListId = parameters.get("id").toLongObject();
+        return seedListService.getSeedList(seedListId);
+      }
+    });
+  }
+
+  public void initPage(IModel<SeedList> model) {
+    setModel(new CompoundPropertyModel<SeedList>(model));
+
+    addBaseForm();
+    addSeedUrlsList();
+    addUrlForm();
+  }
+
+  private void addBaseForm() {
+    Form<SeedList> form = new Form<SeedList>("seedList", getModel()) {
+      @Override
+      protected void onSubmit() {
+        seedListService.save(getModelObject());
+        setResponsePage(SeedListsPage.class);
+      }
+    };
+    form.add(new TextField<String>("name"));
+    add(form);
+  }
+
+  private void addSeedUrlsList() {
+    seedUrlsTable = new WebMarkupContainer("seedUrlsTable");
+    seedUrlsTable.setOutputMarkupId(true);
+
+    RefreshingView<SeedUrl> seedUrls = new RefreshingView<SeedUrl>("seedUrls") {
+
+      @Override
+      protected Iterator<IModel<SeedUrl>> getItemModels() {
+        return new CpmIteratorAdapter<SeedUrl>(getModelObject().getSeedUrls());
+      }
+
+      @Override
+      protected void populateItem(Item<SeedUrl> item) {
+        item.add(new Label("url"));
+        item.add(new AjaxLink<SeedUrl>("delete", item.getModel()) {
+
+          @Override
+          public void onClick(AjaxRequestTarget target) {
+            deleteSeedUrl(getModelObject());
+            target.add(seedUrlsTable);
+          }
+        });
+      }
+    };
+    seedUrlsTable.add(seedUrls);
+    add(seedUrlsTable);
+  }
+
+  private void addUrlForm() {
+    urlForm = new Form<SeedUrl>("urlForm", CompoundPropertyModel.of(Model.of(new SeedUrl())));
+    urlForm.setOutputMarkupId(true);
+    urlForm.add(new TextField<String>("url"));
+    urlForm.add(new AjaxSubmitLink("addUrl", urlForm) {
+      @Override
+      protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
+        addSeedUrl();
+        urlForm.setModelObject(new SeedUrl());
+        target.add(urlForm);
+        target.add(seedUrlsTable);
+      }
+    });
+    add(urlForm);
+  }
+
+  private void addSeedUrl() {
+    SeedUrl url = urlForm.getModelObject();
+    SeedList seedList = getModelObject();
+    url.setSeedList(seedList);
+    seedList.getSeedUrls().add(url);
+  }
+
+  private void deleteSeedUrl(SeedUrl url) {
+    SeedList seedList = getModelObject();
+    seedList.getSeedUrls().remove(url);
+  }
+
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.html
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.html?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.html (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.html Mon Sep 22 14:18:53 2014
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+<head>
+<meta charset="utf-8" />
+<title>Wicket extend</title>
+</head>
+
+<body>
+	<wicket:extend>
+		<h2>
+			<wicket:message key="settings">Settings</wicket:message>
+		</h2>
+		<div class="row">
+			<div class="col-lg-12">
+				<table class="table table-hover tablesorter table-bordered">
+					<thead>
+						<tr>
+							<th class="header col-lg-3">
+								<wicket:message key="settings.header.name">Name</wicket:message>
+							</th>
+							<th class="header col-lg-9">
+								<wicket:message key="settings.header.value">Value</wicket:message>
+							</th>
+						</tr>
+					</thead>
+					<tbody wicket:id="settingsTable">
+						<tr wicket:id="settings">
+							<td>
+								<span wicket:id="name">Name</span>
+							</td>
+							<td>
+<!-- 								<span wicket:id="value">Value</span> -->
+					<input class="col-lg-12" wicket:id="value" placeholder="http://localhost:8080">
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</div>
+		</div>
+	</wicket:extend>
+
+</body>
+</html>

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/pages/settings/SettingsPage.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,57 @@
+package org.apache.nutch.webui.pages.settings;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.nutch.webui.model.NutchConfig;
+import org.apache.nutch.webui.pages.AbstractBasePage;
+import org.apache.nutch.webui.pages.components.CpmIteratorAdapter;
+import org.apache.nutch.webui.service.NutchService;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.RefreshingView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class SettingsPage extends AbstractBasePage<Void> {
+  @SpringBean
+  private NutchService nutchService;
+
+  private WebMarkupContainer settingsTable;
+
+  public SettingsPage() {
+    settingsTable = new WebMarkupContainer("settingsTable");
+    settingsTable.setOutputMarkupId(true);
+    RefreshingView<NutchConfig> nutchConfig = new RefreshingView<NutchConfig>("settings") {
+
+      @Override
+      protected Iterator<IModel<NutchConfig>> getItemModels() {
+        return new CpmIteratorAdapter<NutchConfig>(
+            convertNutchConfig(nutchService.getNutchConfig(getCurrentInstance().getId())));
+      }
+
+      @Override
+      protected void populateItem(Item<NutchConfig> item) {
+        item.add(new Label("name"));
+        item.add(new TextField<String>("value"));
+      }
+    };
+    settingsTable.add(nutchConfig);
+    add(settingsTable);
+  }
+
+  private List<NutchConfig> convertNutchConfig(Map<String, String> map) {
+    List<NutchConfig> listNutchConfigs = new LinkedList<NutchConfig>();
+    for (String key : map.keySet()) {
+      NutchConfig conf = new NutchConfig();
+      conf.setName(key);
+      conf.setValue(map.get(key));
+      listNutchConfigs.add(conf);
+    }
+    return listNutchConfigs;
+  }
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/CrawlService.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/CrawlService.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/CrawlService.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/CrawlService.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service;
+
+import java.util.List;
+
+import org.apache.nutch.webui.client.model.Crawl;
+import org.apache.nutch.webui.model.NutchInstance;
+
+public interface CrawlService {
+  
+  public void saveCrawl(Crawl crawl);
+
+  public List<Crawl> getCrawls();
+
+  void startCrawl(Long crawlId, NutchInstance instance);
+
+  void deleteCrawl(Long crawlId);
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchInstanceService.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchInstanceService.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchInstanceService.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchInstanceService.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service;
+
+import java.util.List;
+
+import org.apache.nutch.webui.model.NutchInstance;
+
+public interface NutchInstanceService {
+
+  public List<NutchInstance> getInstances();
+
+  public void saveInstance(NutchInstance instance);
+
+  public void removeInstance(Long id);
+
+  public NutchInstance getInstance(Long id);
+
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchService.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchService.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchService.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/NutchService.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service;
+
+import java.util.Map;
+
+import org.apache.nutch.webui.client.model.ConnectionStatus;
+import org.apache.nutch.webui.client.model.NutchStatus;
+
+public interface NutchService {
+  public ConnectionStatus getConnectionStatus(Long instanceId);
+
+  public  Map<String, String> getNutchConfig(Long instanceId);
+  
+  public NutchStatus getNutchStatus(Long instanceId);
+
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/SeedListService.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/SeedListService.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/SeedListService.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/SeedListService.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service;
+
+import java.util.List;
+
+import org.apache.nutch.webui.model.SeedList;
+
+public interface SeedListService {
+
+  public void save(SeedList seedList);
+
+  public void delete(Long seedListId);
+
+  public List<SeedList> findAll();
+
+  public SeedList getSeedList(Long seedListId);
+
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/CrawlServiceImpl.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/CrawlServiceImpl.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/CrawlServiceImpl.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/CrawlServiceImpl.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service.impl;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.apache.nutch.webui.client.NutchClient;
+import org.apache.nutch.webui.client.NutchClientFactory;
+import org.apache.nutch.webui.client.impl.CrawlingCycle;
+import org.apache.nutch.webui.client.impl.RemoteCommandsBatchFactory;
+import org.apache.nutch.webui.client.impl.CrawlingCycleListener;
+import org.apache.nutch.webui.client.impl.RemoteCommand;
+import org.apache.nutch.webui.client.impl.RemoteCommandExecutor;
+import org.apache.nutch.webui.client.model.Crawl;
+import org.apache.nutch.webui.client.model.Crawl.CrawlStatus;
+import org.apache.nutch.webui.model.NutchInstance;
+import org.apache.nutch.webui.service.CrawlService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import com.j256.ormlite.dao.Dao;
+
+@Service
+public class CrawlServiceImpl implements CrawlService, CrawlingCycleListener {
+  private Logger log = LoggerFactory.getLogger(CrawlServiceImpl.class);
+
+  @Resource
+  private Dao<Crawl, Long> crawlDao;
+
+  @Resource
+  private NutchClientFactory nutchClientFactory;
+
+  @Resource
+  private RemoteCommandsBatchFactory commandFactory;
+
+  @Override
+  @Async
+  public void startCrawl(Long crawlId, NutchInstance instance) {
+    Crawl crawl = null;
+    try {
+      crawl = crawlDao.queryForId(crawlId);
+      NutchClient client = nutchClientFactory.getClient(instance);
+      String seedDirectory = client.createSeed(crawl.getSeedList());
+      crawl.setSeedDirectory(seedDirectory);
+
+      List<RemoteCommand> commands = commandFactory.createCommands(crawl);
+      RemoteCommandExecutor executor = new RemoteCommandExecutor(client);
+
+      CrawlingCycle cycle = new CrawlingCycle(this, executor, crawl, commands);
+      cycle.executeCrawlCycle();
+      
+    } catch (Exception e) {
+      crawl.setStatus(CrawlStatus.ERROR);
+      saveCrawl(crawl);
+      log.error("exception occured", e);
+    }
+  }
+
+  @Override
+  public List<Crawl> getCrawls() {
+    try {
+      return crawlDao.queryForAll();
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void saveCrawl(Crawl crawl) {
+    try {
+      crawlDao.createOrUpdate(crawl);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void deleteCrawl(Long crawlId) {
+    try {
+      crawlDao.deleteById(crawlId);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void crawlingStarted(Crawl crawl) {
+    crawl.setStatus(CrawlStatus.CRAWLING);
+    crawl.setProgress(0);
+    saveCrawl(crawl);
+  }
+
+  @Override
+  public void onCrawlError(Crawl crawl, String msg) {
+    crawl.setStatus(CrawlStatus.ERROR);
+    saveCrawl(crawl);
+  }
+
+  @Override
+  public void commandExecuted(Crawl crawl, RemoteCommand command, int progress) {
+    crawl.setProgress(progress);
+    saveCrawl(crawl);
+  }
+
+  @Override
+  public void crawlingFinished(Crawl crawl) {
+    crawl.setStatus(CrawlStatus.FINISHED);
+    saveCrawl(crawl);
+  }
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchInstanceServiceImpl.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchInstanceServiceImpl.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchInstanceServiceImpl.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchInstanceServiceImpl.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service.impl;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.apache.nutch.webui.client.NutchClientFactory;
+import org.apache.nutch.webui.model.NutchInstance;
+import org.apache.nutch.webui.service.NutchInstanceService;
+import org.springframework.stereotype.Service;
+
+import com.j256.ormlite.dao.Dao;
+
+@Service
+public class NutchInstanceServiceImpl implements NutchInstanceService {
+
+  @Resource
+  private NutchClientFactory nutchClientFactory;
+
+  @Resource
+  private Dao<NutchInstance, Long> instancesDao;
+
+  @Override
+  public List<NutchInstance> getInstances() {
+    try {
+      return instancesDao.queryForAll();
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+
+  }
+
+  @Override
+  public NutchInstance getInstance(Long id) {
+    try {
+      return instancesDao.queryForId(id);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void saveInstance(NutchInstance instance) {
+    try {
+      instancesDao.createOrUpdate(instance);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void removeInstance(Long id) {
+    try {
+      instancesDao.deleteById(id);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchServiceImpl.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchServiceImpl.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchServiceImpl.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/NutchServiceImpl.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service.impl;
+
+import java.net.ConnectException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.apache.nutch.webui.client.NutchClientFactory;
+import org.apache.nutch.webui.client.model.ConnectionStatus;
+import org.apache.nutch.webui.client.model.NutchStatus;
+import org.apache.nutch.webui.model.NutchInstance;
+import org.apache.nutch.webui.service.NutchInstanceService;
+import org.apache.nutch.webui.service.NutchService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+
+@Service
+public class NutchServiceImpl implements NutchService {
+  private static final Logger logger = LoggerFactory.getLogger(NutchServiceImpl.class);
+
+  @Resource
+  private NutchClientFactory nutchClientFactory;
+
+  @Resource
+  private NutchInstanceService instanceService;
+
+  @Override
+  public ConnectionStatus getConnectionStatus(Long instanceId) {
+    NutchInstance instance = instanceService.getInstance(instanceId);
+    try {
+      NutchStatus nutchStatus = nutchClientFactory.getClient(instance)
+          .getNutchStatus();
+      if (nutchStatus.getStartDate() != null) {
+        return ConnectionStatus.CONNECTED;
+      }
+    } catch (Exception e) {
+      if (e.getCause() instanceof ConnectException) {
+        return ConnectionStatus.DISCONNECTED;
+      }
+
+      logger.error("Cannot connect to nutch server!", e);
+    }
+    return null;
+  }
+
+  @Override
+  public Map<String, String> getNutchConfig(Long instanceId) {
+    NutchInstance instance = instanceService.getInstance(instanceId);
+    try {
+      return nutchClientFactory.getClient(instance).getNutchConfig("default");
+    } catch (ClientHandlerException exception) {
+      return Collections.emptyMap();
+    }
+  }
+
+  @Override
+  public NutchStatus getNutchStatus(Long instanceId) {
+    NutchInstance instance = instanceService.getInstance(instanceId);
+    return nutchClientFactory.getClient(instance).getNutchStatus();
+  }
+}

Added: nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/SeedListServiceImpl.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/SeedListServiceImpl.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/SeedListServiceImpl.java (added)
+++ nutch/branches/2.x/src/java/org/apache/nutch/webui/service/impl/SeedListServiceImpl.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.service.impl;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.apache.nutch.webui.model.SeedList;
+import org.apache.nutch.webui.model.SeedUrl;
+import org.apache.nutch.webui.service.SeedListService;
+import org.springframework.stereotype.Service;
+
+import com.j256.ormlite.dao.Dao;
+
+@Service
+public class SeedListServiceImpl implements SeedListService {
+
+  @Resource
+  private Dao<SeedList, Long> seedListDao;
+
+  @Resource
+  private Dao<SeedUrl, Long> seedUrlDao;
+
+  @Override
+  public void save(SeedList seedList) {
+    try {
+      seedListDao.createOrUpdate(seedList);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public void delete(Long seedListId) {
+    try {
+      seedListDao.deleteById(seedListId);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+
+  }
+
+  @Override
+  public List<SeedList> findAll() {
+    try {
+      return seedListDao.queryForAll();
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public SeedList getSeedList(Long seedListId) {
+    try {
+      return seedListDao.queryForId(seedListId);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestCrawlCycle.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestCrawlCycle.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestCrawlCycle.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestCrawlCycle.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.client;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.GENERATE;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.INJECT;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
+import java.util.List;
+
+import org.apache.nutch.webui.client.impl.CrawlingCycle;
+import org.apache.nutch.webui.client.impl.CrawlingCycleListener;
+import org.apache.nutch.webui.client.impl.RemoteCommand;
+import org.apache.nutch.webui.client.impl.RemoteCommandBuilder;
+import org.apache.nutch.webui.client.impl.RemoteCommandExecutor;
+import org.apache.nutch.webui.client.model.Crawl;
+import org.apache.nutch.webui.client.model.JobInfo;
+import org.apache.nutch.webui.client.model.JobInfo.State;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestCrawlCycle {
+  @Mock
+  private RemoteCommandExecutor executor;
+
+  @Mock
+  private CrawlingCycleListener listener;
+
+  private CrawlingCycle crawlingCycle;
+
+  @Captor
+  private ArgumentCaptor<RemoteCommand> remoteCommandCaptor;
+
+  @Before
+  public void setUp() {
+    JobInfo jobInfo = new JobInfo();
+    jobInfo.setState(State.FINISHED);
+    given(executor.executeRemoteJob(any(RemoteCommand.class))).willReturn(jobInfo);
+  }
+
+  @Test
+  public void shouldInvokeCrawlStartedAndFinished() {
+    // given
+    List<RemoteCommand> commands = newArrayList(RemoteCommandBuilder.instance(INJECT).build());
+    Crawl crawl = new Crawl();
+
+    crawlingCycle = new CrawlingCycle(listener, executor, crawl, commands);
+
+    // when
+    crawlingCycle.executeCrawlCycle();
+
+    // then
+    verify(listener, times(1)).crawlingStarted(crawl);
+    verify(listener, times(1)).crawlingFinished(crawl);
+  }
+
+  @Test
+  public void shouldInvokeOnError() {
+    // given
+    List<RemoteCommand> commands = newArrayList(RemoteCommandBuilder.instance(INJECT).build());
+    Crawl crawl = new Crawl();
+    crawlingCycle = new CrawlingCycle(listener, executor, crawl, commands);
+    JobInfo jobInfo = new JobInfo();
+    jobInfo.setMsg("Some error message");
+    jobInfo.setState(State.FAILED);
+
+    given(executor.executeRemoteJob(any(RemoteCommand.class))).willReturn(jobInfo);
+
+    // when
+    crawlingCycle.executeCrawlCycle();
+
+    // then
+    verify(listener, times(1)).onCrawlError(crawl, jobInfo.getMsg());
+  }
+
+  @Test
+  public void shouldCalculateProgress() {
+    // given
+    RemoteCommand firstCommand = RemoteCommandBuilder.instance(INJECT).build();
+    RemoteCommand secondCommand = RemoteCommandBuilder.instance(GENERATE).build();
+    List<RemoteCommand> commands = newArrayList(firstCommand, secondCommand);
+
+    Crawl crawl = new Crawl();
+    crawlingCycle = new CrawlingCycle(listener, executor, crawl, commands);
+
+    // when
+    crawlingCycle.executeCrawlCycle();
+
+    // then
+    verify(listener, times(1)).commandExecuted(crawl, firstCommand, 50);
+    verify(listener, times(1)).commandExecuted(crawl, secondCommand, 100);
+  }
+
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestNutchClientFactory.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestNutchClientFactory.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestNutchClientFactory.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestNutchClientFactory.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.client;
+
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import org.apache.nutch.webui.model.NutchInstance;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestNutchClientFactory {
+  
+  @InjectMocks
+  private NutchClientFactory factory;
+
+  @Test
+  public void shouldReturnClientWithCorrectInstance() {
+    // given
+    NutchInstance instance = new NutchInstance();
+
+    // when
+    NutchClient client = factory.getClient(instance);
+
+    // then
+    assertSame(instance, client.getNutchInstance());
+  }
+
+  @Test
+  public void shouldReturnTheSameClient() {
+    // given
+    NutchInstance instance = new NutchInstance();
+
+    // when
+    NutchClient client = factory.getClient(instance);
+    NutchClient client2 = factory.getClient(instance);
+
+    // then
+    assertSame(client, client2);
+  }
+  
+  @Test
+  public void shouldReturnNewClientForOtherInstance() {
+    // given
+    NutchInstance instance = new NutchInstance();
+    NutchInstance otherInstance = new NutchInstance();
+
+    // when
+    NutchClient client = factory.getClient(instance);
+    NutchClient client2 = factory.getClient(otherInstance);
+
+    // then
+    assertNotSame(client, client2);
+  }
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandExecutor.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandExecutor.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandExecutor.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandExecutor.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.client;
+
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.anyString;
+
+import org.apache.nutch.webui.client.impl.RemoteCommand;
+import org.apache.nutch.webui.client.impl.RemoteCommandBuilder;
+import org.apache.nutch.webui.client.impl.RemoteCommandExecutor;
+import org.apache.nutch.webui.client.model.JobInfo;
+import org.apache.nutch.webui.client.model.JobInfo.JobType;
+import org.apache.nutch.webui.client.model.JobInfo.State;
+import org.joda.time.Duration;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestRemoteCommandExecutor {
+  private static final int REQUEST_DELAY = 10;
+
+  @Mock
+  private NutchClient client;
+
+  @InjectMocks
+  private RemoteCommandExecutor remoteExecutor = new RemoteCommandExecutor(client);
+
+  @Before
+  public void setUp() {
+    remoteExecutor.setRequestDelay(Duration.millis(REQUEST_DELAY));
+  }
+
+  @Test
+  public void shouldExecuteCommandRemotely() {
+    // given
+    RemoteCommand command = RemoteCommandBuilder.instance(JobType.INJECT).build();
+    JobInfo jobInfo = new JobInfo();
+    jobInfo.setState(State.FINISHED);
+    given(client.getJobInfo(anyString())).willReturn(jobInfo);
+
+    // when
+    JobInfo info = remoteExecutor.executeRemoteJob(command);
+
+    // then
+    assertEquals(State.FINISHED, info.getState());
+  }
+
+  @Test
+  public void shouldWaitUntilExecutionComplete() {
+    // given
+    RemoteCommand command = RemoteCommandBuilder.instance(JobType.INJECT)
+        .withTimeout(Duration.standardSeconds(1)).build();
+    JobInfo jobInfo = new JobInfo();
+    jobInfo.setState(State.RUNNING);
+
+    JobInfo newJobInfo = new JobInfo();
+    newJobInfo.setState(State.FINISHED);
+    given(client.getJobInfo(anyString())).willReturn(jobInfo, newJobInfo);
+
+    // when
+    JobInfo info = remoteExecutor.executeRemoteJob(command);
+
+    // then
+    assertEquals(State.FINISHED, info.getState());
+  }
+
+  @Test
+  public void shouldThrowExceptionOnTimeout() {
+    // given
+    RemoteCommand command = RemoteCommandBuilder.instance(JobType.INJECT)
+        .withTimeout(Duration.millis(REQUEST_DELAY / 2)).build();
+
+    JobInfo jobInfo = new JobInfo();
+    jobInfo.setState(State.RUNNING);
+
+    given(client.getJobInfo(anyString())).willReturn(jobInfo);
+
+    // when
+    JobInfo info = remoteExecutor.executeRemoteJob(command);
+
+    // then
+    assertEquals(State.FAILED, info.getState());
+  }
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandsBatchFactory.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandsBatchFactory.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandsBatchFactory.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/client/TestRemoteCommandsBatchFactory.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.client;
+
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.FETCH;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.GENERATE;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.INDEX;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.INJECT;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.PARSE;
+import static org.apache.nutch.webui.client.model.JobInfo.JobType.UPDATEDB;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.apache.nutch.webui.client.impl.RemoteCommand;
+import org.apache.nutch.webui.client.impl.RemoteCommandsBatchFactory;
+import org.apache.nutch.webui.client.model.Crawl;
+import org.apache.nutch.webui.client.model.JobInfo.JobType;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.google.common.collect.Lists;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestRemoteCommandsBatchFactory {
+  private RemoteCommandsBatchFactory factory;
+
+  private List<JobType> executionSequence = Lists.newArrayList(INJECT, GENERATE, FETCH, PARSE,
+      UPDATEDB, INDEX, GENERATE, FETCH, PARSE, UPDATEDB, INDEX);
+
+  @Before
+  public void setUp() {
+    factory = new RemoteCommandsBatchFactory();
+  }
+
+  @Test
+  public void commandsShouldBeInCorrectSequence() {
+    // given
+    Crawl crawl = new Crawl();
+    crawl.setNumberOfRounds(2);
+
+    // when
+    List<RemoteCommand> commands = factory.createCommands(crawl);
+
+    // then
+    for (int i = 0; i < commands.size(); i++) {
+      assertTrue(commands.get(i).getJobConfig().getType() == executionSequence.get(i));
+    }
+  }
+
+  @Test
+  public void batchIdShouldBeUnique() {
+    // given
+    Crawl crawl = new Crawl();
+    crawl.setNumberOfRounds(2);
+
+    // when
+    List<RemoteCommand> commands = factory.createCommands(crawl);
+
+    // then
+    String batchId = (String) commands.get(1).getJobConfig().getArgs().get("batch");
+    String secondBatchId = (String) commands.get(7).getJobConfig().getArgs().get("batch");
+    assertNotEquals(batchId, secondBatchId);
+  }
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/service/NutchServiceTest.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/service/NutchServiceTest.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/service/NutchServiceTest.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/service/NutchServiceTest.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,65 @@
+package org.apache.nutch.webui.service;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+
+import java.util.Map;
+
+import org.apache.commons.collections4.MapUtils;
+import org.apache.nutch.webui.client.NutchClientFactory;
+import org.apache.nutch.webui.client.impl.NutchClientImpl;
+import org.apache.nutch.webui.model.NutchInstance;
+import org.apache.nutch.webui.service.impl.NutchServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.google.common.collect.Maps;
+import com.sun.jersey.api.client.ClientHandlerException;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NutchServiceTest {
+
+  @Mock
+  private NutchClientFactory clientFactory;
+
+  @Mock
+  private NutchInstanceService instanceService;
+
+  @Mock
+  private NutchClientImpl client;
+
+  @InjectMocks
+  private NutchServiceImpl nutchService;
+
+  @Test
+  public void shouldReturnEmptyMapOnException() {
+    // given
+    given(clientFactory.getClient(any(NutchInstance.class))).willReturn(client);
+    given(client.getNutchConfig("default")).willThrow(new ClientHandlerException("Error!"));
+
+    // when
+    Map<String, String> config = nutchService.getNutchConfig(1L);
+
+    // then
+    assertTrue(MapUtils.isEmpty(config));
+  }
+
+  @Test
+  public void shouldGetCorrectConfiguration() {
+    // given
+    Map<String, String> configMap = Maps.newHashMap();
+    given(clientFactory.getClient(any(NutchInstance.class))).willReturn(client);
+    given(client.getNutchConfig("default")).willReturn(configMap);
+
+    // when
+    Map<String, String> config = nutchService.getNutchConfig(1L);
+
+    // then
+    assertSame(configMap, config);
+  }
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/view/AbstractWicketTest.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/view/AbstractWicketTest.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/view/AbstractWicketTest.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/view/AbstractWicketTest.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.view;
+
+import javax.annotation.Resource;
+
+import org.apache.wicket.util.tester.WicketTester;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = SpringConfigForTests.class, loader = AnnotationConfigContextLoader.class)
+public abstract class AbstractWicketTest {
+  @Resource
+  protected WicketTester tester;
+}

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/view/SpringConfigForTests.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/view/SpringConfigForTests.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/view/SpringConfigForTests.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/view/SpringConfigForTests.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,36 @@
+package org.apache.nutch.webui.view;
+
+import java.sql.SQLException;
+
+import javax.annotation.Resource;
+
+import org.apache.nutch.webui.NutchUiApplication;
+import org.apache.wicket.util.tester.WicketTester;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import com.j256.ormlite.db.H2DatabaseType;
+import com.j256.ormlite.jdbc.JdbcConnectionSource;
+
+@Configuration
+@ComponentScan("org.apache.nutch.webui")
+public class SpringConfigForTests {
+
+  @Resource
+  private NutchUiApplication application;
+
+  @Bean
+  public WicketTester getTester() {
+    WicketTester wicketTester = new WicketTester(application);
+    application.getMarkupSettings().setStripWicketTags(false);
+    return wicketTester;
+  }
+
+  @Bean
+  public JdbcConnectionSource getConnectionSource() throws SQLException {
+    JdbcConnectionSource source = new JdbcConnectionSource("jdbc:h2:mem:", new H2DatabaseType());
+    source.initialize();
+    return source;
+  }
+}
\ No newline at end of file

Added: nutch/branches/2.x/src/test/org/apache/nutch/webui/view/TestColorEnumLabel.java
URL: http://svn.apache.org/viewvc/nutch/branches/2.x/src/test/org/apache/nutch/webui/view/TestColorEnumLabel.java?rev=1626786&view=auto
==============================================================================
--- nutch/branches/2.x/src/test/org/apache/nutch/webui/view/TestColorEnumLabel.java (added)
+++ nutch/branches/2.x/src/test/org/apache/nutch/webui/view/TestColorEnumLabel.java Mon Sep 22 14:18:53 2014
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nutch.webui.view;
+
+import static de.agilecoders.wicket.core.markup.html.bootstrap.block.LabelType.Success;
+import static org.apache.nutch.webui.client.model.ConnectionStatus.CONNECTED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.nutch.webui.client.model.ConnectionStatus;
+import org.apache.nutch.webui.pages.components.ColorEnumLabel;
+import org.apache.nutch.webui.pages.components.ColorEnumLabelBuilder;
+import org.apache.wicket.model.Model;
+import org.junit.Test;
+
+public class TestColorEnumLabel extends AbstractWicketTest {
+
+  @Test
+  public void shouldRenderCorrectText() {
+    // given
+    Model<ConnectionStatus> model = Model.of(ConnectionStatus.CONNECTED);
+    ColorEnumLabel<ConnectionStatus> label = new ColorEnumLabelBuilder<ConnectionStatus>("status")
+        .withModel(model).build();
+
+    // when
+    tester.startComponentInPage(label);
+
+    // then
+    assertEquals("Connected", tester.getTagByWicketId("status").getValue());
+  }
+
+  @Test
+  public void shouldChangeColorOfLabel() {
+    // given
+    Model<ConnectionStatus> model = Model.of(ConnectionStatus.CONNECTED);
+    ColorEnumLabel<ConnectionStatus> label = new ColorEnumLabelBuilder<ConnectionStatus>("status")
+        .withEnumColor(CONNECTED, Success).withModel(model).build();
+
+    // when
+    tester.startComponentInPage(label);
+
+    // then
+    assertTrue(tester.getTagByWicketId("status").getAttributeEndsWith("class", "success"));
+  }
+}