You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2012/03/15 08:37:20 UTC
svn commit: r1300825 - in
/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin:
AddArtifactWindow.java ArtifactTable.java VaadinClient.java
Author: marrs
Date: Thu Mar 15 07:37:19 2012
New Revision: 1300825
URL: http://svn.apache.org/viewvc?rev=1300825&view=rev
Log:
ACE-228 applied the patch, works nicely
Modified:
ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AddArtifactWindow.java
ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java
ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java
Modified: ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AddArtifactWindow.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AddArtifactWindow.java?rev=1300825&r1=1300824&r2=1300825&view=diff
==============================================================================
--- ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AddArtifactWindow.java (original)
+++ ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AddArtifactWindow.java Thu Mar 15 07:37:19 2012
@@ -18,6 +18,7 @@
*/
package org.apache.ace.webui.vaadin;
+import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -28,6 +29,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
@@ -45,6 +47,7 @@ import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
@@ -53,187 +56,300 @@ import com.vaadin.terminal.StreamVariabl
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
+import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Html5File;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
+import com.vaadin.ui.Upload.FailedListener;
import com.vaadin.ui.Upload.SucceededEvent;
+import com.vaadin.ui.Upload.SucceededListener;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
-@SuppressWarnings("serial")
-class AddArtifactWindow extends Window {
- private volatile LogService m_log;
- private volatile ArtifactRepository m_artifactRepository;
- private File m_file;
- private Window m_main;
- private List<File> m_uploadedArtifacts = new ArrayList<File>();
- private File m_sessionDir;
- private List<OBREntry> m_obrList;
- private URL m_obrUrl;
-
- public AddArtifactWindow(final Window main, LogService log,
- File sessionDir, List<OBREntry> obrList, URL obrUrl,
- ArtifactRepository artifactRepository) {
- super();
- m_main = main;
- m_log = log;
- m_sessionDir = sessionDir;
- m_obrList = obrList;
- m_obrUrl = obrUrl;
- m_artifactRepository = artifactRepository;
+/**
+ * Provides a dialog for uploading new artifacts to ACE, or selecting existing artifacts from the repository.
+ */
+abstract class AddArtifactWindow extends Window {
- setModal(true);
- setCaption("Add artifact");
- setWidth("50em");
+ /**
+ * Provides a {@link DropHandler} implementation for handling dropped artifacts.
+ */
+ private static final class ArtifactDropHandler implements DropHandler {
+ private final StreamVariable m_html5uploadStreamVariable;
+
+ private ArtifactDropHandler(StreamVariable html5uploadStreamVariable) {
+ m_html5uploadStreamVariable = html5uploadStreamVariable;
+ }
+
+ /*
+ * @see com.vaadin.event.dd.DropHandler#drop(com.vaadin.event.dd.DragAndDropEvent)
+ */
+ public void drop(DragAndDropEvent dropEvent) {
+ // expecting this to be an html5 drag
+ WrapperTransferable tr = (WrapperTransferable) dropEvent.getTransferable();
+ Html5File[] files = tr.getFiles();
+ if (files != null) {
+ for (final Html5File html5File : files) {
+ html5File.setStreamVariable(m_html5uploadStreamVariable);
+ }
+ }
+ }
- VerticalLayout layout = (VerticalLayout) getContent();
- layout.setMargin(true);
- layout.setSpacing(true);
+ /*
+ * @see com.vaadin.event.dd.DropHandler#getAcceptCriterion()
+ */
+ public AcceptCriterion getAcceptCriterion() {
+ // TODO only accept .jar files ?
+ return AcceptAll.get();
+ }
+ }
- final TextField search = new TextField("search");
- final Table artifacts = new ArtifactTable(main);
- final Table uploadedArtifacts = new ArtifactTable(main);
- final Upload uploadArtifact = new Upload("Upload Artifact",
- new Upload.Receiver() {
- public OutputStream receiveUpload(String filename,
- String MIMEType) {
- FileOutputStream fos = null;
- try {
- m_file = new File(m_sessionDir, filename);
- if (m_file.exists()) {
- throw new IOException(
- "Uploaded file already exists.");
- }
- fos = new FileOutputStream(m_file);
- }
- catch (final IOException e) {
- m_main.showNotification(
- "Upload artifact failed",
- "File "
- + m_file.getName()
- + "<br />could not be accepted on the server.<br />"
- + "Reason: " + e.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR, "Upload of "
- + m_file.getAbsolutePath() + " failed.", e);
- return null;
- }
- return fos;
- }
- });
-
- final DragAndDropWrapper finalUploadedArtifacts = new DragAndDropWrapper(
- uploadedArtifacts);
-
- final StreamVariable html5uploadStreamVariable = new StreamVariable() {
- FileOutputStream fos = null;
-
- public OutputStream getOutputStream() {
- return fos;
- }
+ /**
+ * Provides a upload handler capable of handling "old school" uploads, and new HTML5-style uploads.
+ */
+ private static abstract class GenericUploadHandler implements StreamVariable, Upload.SucceededListener,
+ Upload.FailedListener, Upload.Receiver {
+ private final File m_sessionDir;
+
+ private FileOutputStream m_fos = null;
+ private File m_file;
+
+ /**
+ * @param sessionDir the session directory to temporarily store uploaded artifacts in, cannot be <code>null</code>.
+ */
+ private GenericUploadHandler(File sessionDir) {
+ m_sessionDir = sessionDir;
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#getOutputStream()
+ */
+ public final OutputStream getOutputStream() {
+ return m_fos;
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#isInterrupted()
+ */
+ public final boolean isInterrupted() {
+ return (m_fos == null);
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#listenProgress()
+ */
+ public final boolean listenProgress() {
+ return false;
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#onProgress(com.vaadin.terminal.StreamVariable.StreamingProgressEvent)
+ */
+ public final void onProgress(StreamingProgressEvent event) {
+ // Do nothing, no progress indicator (yet ?)
+ }
+
+ /*
+ * @see com.vaadin.ui.Upload.Receiver#receiveUpload(java.lang.String, java.lang.String)
+ */
+ public final OutputStream receiveUpload(String filename, String MIMEType) {
+ return prepareUpload(filename);
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#streamingFailed(com.vaadin.terminal.StreamVariable.StreamingErrorEvent)
+ */
+ public final void streamingFailed(StreamingErrorEvent event) {
+ handleUploadFailure(event.getFileName(), event.getException());
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#streamingFinished(com.vaadin.terminal.StreamVariable.StreamingEndEvent)
+ */
+ public final void streamingFinished(StreamingEndEvent event) {
+ finishUpload();
+ }
+
+ /*
+ * @see com.vaadin.terminal.StreamVariable#streamingStarted(com.vaadin.terminal.StreamVariable.StreamingStartEvent)
+ */
+ public final void streamingStarted(StreamingStartEvent event) {
+ prepareUpload(event.getFileName());
+ }
+
+ /*
+ * @see com.vaadin.ui.Upload.FailedListener#uploadFailed(com.vaadin.ui.Upload.FailedEvent)
+ */
+ public final void uploadFailed(FailedEvent event) {
+ handleUploadFailure(event.getFilename(), event.getReason());
+ }
+
+ /*
+ * @see com.vaadin.ui.Upload.SucceededListener#uploadSucceeded(com.vaadin.ui.Upload.SucceededEvent)
+ */
+ public final void uploadSucceeded(SucceededEvent event) {
+ finishUpload();
+ }
+
+ /**
+ * Called when the upload was successful.
+ *
+ * @param uploadedArtifact the uploaded file to process, never <code>null</code>.
+ */
+ protected abstract void artifactUploaded(File uploadedArtifact);
+
+ /**
+ * Called when the upload failed.
+ *
+ * @param uploadedArtifact the name of the artifact whose upload failed;
+ * @param throwable the (optional) exception that caused the upload to fail.
+ */
+ protected abstract void uploadFailed(String uploadedArtifact, Throwable throwable);
+
+ /**
+ * Called after successfully uploading the artifact. Calls the {@link #artifactUploaded(File)} method.
+ */
+ private void finishUpload() {
+ // Make sure the output stream is properly closed...
+ silentlyClose(m_fos);
- public boolean listenProgress() {
- return false;
+ try {
+ artifactUploaded(m_file);
+ }
+ finally {
+ m_fos = null;
}
+ }
- public void streamingStarted(StreamingStartEvent event) {
- try {
- m_file = new File(m_sessionDir, event.getFileName());
- if (m_file.exists()) {
- throw new IOException("Uploaded file already exists: "
- + event.getFileName());
- }
- fos = new FileOutputStream(m_file);
- }
- catch (final IOException e) {
- m_main.showNotification(
- "Upload artifact failed",
- "File "
- + m_file.getName()
- + "<br />could not be accepted on the server.<br />"
- + "Reason: " + e.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Upload of " + m_file.getAbsolutePath()
- + " failed.", e);
- fos = null;
+ /**
+ * Handles any failures during the upload by closing all streams and cleaning up all resources. Calls the {@link #uploadFailed(String, Throwable)}
+ *
+ * @param fileName the name of the uploaded artifact that failed;
+ * @param throwable the (optional) exception, can be <code>null</code>.
+ */
+ private void handleUploadFailure(String fileName, Throwable throwable) {
+ silentlyClose(m_fos);
+ m_fos = null;
+ m_file.delete();
+
+ uploadFailed(fileName, throwable);
+ }
+
+ /**
+ * Prepares the actual upload by creating a proper {@link FileOutputStream} to (temporarily) store the artifact to.
+ *
+ * @param fileName the name of the uploaded artifact, cannot be <code>null</code>.
+ */
+ private OutputStream prepareUpload(String fileName) {
+ try {
+ m_file = new File(m_sessionDir, fileName);
+
+ if (m_file.exists()) {
+ throw new IOException("Uploaded file already exists: " + fileName);
}
+ m_fos = new FileOutputStream(m_file);
+ }
+ catch (final IOException e) {
+ uploadFailed(fileName, e);
+ m_fos = null;
}
+ return m_fos;
+ }
- public void streamingFinished(StreamingEndEvent event) {
+ /**
+ * Silently closes the given {@link Closeable} implementation, ignoring any errors that come out of the {@link Closeable#close()} method.
+ *
+ * @param closable the closeable to close, can be <code>null</code>.
+ */
+ private void silentlyClose(Closeable closable) {
+ if (closable != null) {
try {
- URL artifact = m_file.toURI().toURL();
- Item item = uploadedArtifacts.addItem(artifact);
- item.getItemProperty("symbolic name").setValue(
- m_file.getName());
- item.getItemProperty("version").setValue("");
- m_uploadedArtifacts.add(m_file);
- fos.close();
+ closable.close();
}
catch (IOException e) {
- m_main.showNotification(
- "Upload artifact processing failed",
- "<br />Reason: " + e.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Processing of " + m_file.getAbsolutePath()
- + " failed.", e);
- }
- finally {
- fos = null;
+ // Best effort; nothing we can (or want) do about this...
}
}
+ }
+ }
- public void streamingFailed(StreamingErrorEvent event) {
- m_main.showNotification("Upload artifact failed", "File "
- + m_file.getName()
- + "<br />could not be accepted on the server.<br />"
- + "Reason: " + event.getException().getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Upload of " + event.getFileName() + " failed.");
- m_file.delete();
- fos = null;
- }
+ private static final String REPOSITORY_XML = "repository.xml";
+ private static final String XPATH_QUERY = "/repository/resource[@uri]";
- public boolean isInterrupted() {
- return fos == null;
- }
+ private final File m_sessionDir;
+ private final URL m_obrUrl;
- public void onProgress(StreamingProgressEvent event) {
- // Do nothing, no progress indicator (yet ?)
- }
+ private final List<File> m_uploadedArtifacts = new ArrayList<File>();
+ private final Button m_searchButton;
+ private final Button m_closeButton;
+
+ /**
+ * Creates a new {@link AddArtifactWindow} instance.
+ *
+ * @param sessionDir the session directory to temporary place artifacts in;
+ * @param obrUrl the URL of the OBR to use.
+ */
+ public AddArtifactWindow(File sessionDir, URL obrUrl) {
+ super("Add artifact");
- };
+ m_sessionDir = sessionDir;
+ m_obrUrl = obrUrl;
+
+ setModal(true);
+ setWidth("50em");
+
+ final Table artifacts = new ArtifactTable();
+ artifacts.setCaption("Artifacts in repository");
+
+ final IndexedContainer dataSource = (IndexedContainer) artifacts.getContainerDataSource();
+
+ final Table uploadedArtifacts = new ArtifactTable();
+ uploadedArtifacts.setCaption("Uploaded artifacts");
+ uploadedArtifacts.setSelectable(false);
+
+ final GenericUploadHandler uploadHandler = new GenericUploadHandler(m_sessionDir) {
+ @Override
+ protected void artifactUploaded(File uploadedArtifact) {
+ try {
+ URL artifact = uploadedArtifact.toURI().toURL();
- final DropHandler html5uploadDropHandler = new DropHandler() {
+ Item item = uploadedArtifacts.addItem(artifact);
+ item.getItemProperty(ArtifactTable.PROPERTY_SYMBOLIC_NAME).setValue(uploadedArtifact.getName());
+ item.getItemProperty(ArtifactTable.PROPERTY_VERSION).setValue("");
- public void drop(DragAndDropEvent dropEvent) {
- // expecting this to be an html5 drag
- WrapperTransferable tr = (WrapperTransferable) dropEvent
- .getTransferable();
- Html5File[] files = tr.getFiles();
- if (files != null) {
- for (final Html5File html5File : files) {
- html5File.setStreamVariable(html5uploadStreamVariable);
- }
+ m_uploadedArtifacts.add(uploadedArtifact);
+ }
+ catch (MalformedURLException e) {
+ showErrorNotification("Upload artifact processing failed", "<br />Reason: " + e.getMessage());
+ logError("Processing of " + uploadedArtifact + " failed.", e);
}
}
- public AcceptCriterion getAcceptCriterion() {
- // TODO only accept .jar files ?
- return AcceptAll.get();
- }
+ @Override
+ protected void uploadFailed(String uploadedArtifact, Throwable throwable) {
+ showErrorNotification("Upload artifact failed", "File "
+ + uploadedArtifact
+ + "<br />could not be accepted on the server.<br />"
+ + "Reason: " + throwable);
+ logError("Upload of " + uploadedArtifact + " failed.");
+ }
};
- finalUploadedArtifacts.setDropHandler(html5uploadDropHandler);
+ final Upload uploadArtifact = new Upload("Upload Artifact", uploadHandler);
+ uploadArtifact.addListener((SucceededListener) uploadHandler);
+ uploadArtifact.addListener((FailedListener) uploadHandler);
+ uploadArtifact.setImmediate(true);
+
+ final DragAndDropWrapper finalUploadedArtifacts = new DragAndDropWrapper(uploadedArtifacts);
+ finalUploadedArtifacts.setDropHandler(new ArtifactDropHandler(uploadHandler));
- this.addListener(new Window.CloseListener() {
+ addListener(new Window.CloseListener() {
public void windowClose(CloseEvent e) {
for (File artifact : m_uploadedArtifacts) {
artifact.delete();
@@ -241,151 +357,341 @@ class AddArtifactWindow extends Window {
}
});
- artifacts.setCaption("Artifacts in repository");
- uploadedArtifacts.setCaption("Uploaded artifacts");
- uploadedArtifacts.setSelectable(false);
+ HorizontalLayout searchBar = new HorizontalLayout();
+ searchBar.setMargin(false);
+ searchBar.setSpacing(true);
+
+ final TextField searchField = new TextField();
+ searchField.setImmediate(true);
+ searchField.setValue("");
+
+ m_searchButton = new Button("Search", new ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ String searchValue = (String) searchField.getValue();
+
+ dataSource.removeAllContainerFilters();
+
+ if (searchValue != null && searchValue.trim().length() > 0) {
+ dataSource.addContainerFilter(ArtifactTable.PROPERTY_SYMBOLIC_NAME, searchValue,
+ true /* ignoreCase */, false /* onlyMatchPrefix */);
+ }
+ }
+ });
+ m_searchButton.setImmediate(true);
+
+ searchBar.addComponent(searchField);
+ searchBar.addComponent(m_searchButton);
+
+ m_closeButton = new Button("Add", new ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ // Import all "local" (existing) bundles...
+ importLocalBundles(artifacts);
+ // Import all "remote" (non existing) bundles...
+ importRemoteBundles(m_uploadedArtifacts);
+
+ closeWindow();
+
+ // TODO: make a decision here so now we have enough information
+ // to show a list of imported artifacts (added) but do we want
+ // to show this list or do we just assume the user will see the
+ // new artifacts in the left most column? do we also report
+ // failures? or only report if there were failures?
+ }
+ });
+ m_closeButton.setImmediate(true);
+
+ VerticalLayout layout = (VerticalLayout) getContent();
+ layout.setMargin(true);
+ layout.setSpacing(true);
+
+ layout.addComponent(searchBar);
+ layout.addComponent(artifacts);
+ layout.addComponent(uploadArtifact);
+ layout.addComponent(finalUploadedArtifacts);
+ // The components added to the window are actually added to the window's
+ // layout; you can use either. Alignments are set using the layout
+ layout.addComponent(m_closeButton);
+ layout.setComponentAlignment(m_closeButton, Alignment.MIDDLE_RIGHT);
- search.setValue("");
try {
getBundles(artifacts);
}
catch (Exception e) {
- e.printStackTrace();
+ showErrorNotification("Failed to retrieve OBR repository!", "Reason: <br/>" + e.getMessage());
+ logError("Failed to retrieve OBR repository!", e);
}
- uploadArtifact.setImmediate(true);
+ searchField.focus();
+ }
+
+ /**
+ * Gets the actual text from a named item contained in the given node map.
+ *
+ * @param map the node map to get the named item from;
+ * @param name the name of the item to get.
+ * @return the text of the named item, can be <code>null</code> in case the named item does not exist, or has no text.
+ */
+ private static String getNamedItemText(NamedNodeMap map, String name) {
+ Node namedItem = map.getNamedItem(name);
+ if (namedItem == null) {
+ return null;
+ }
+ else {
+ return namedItem.getTextContent();
+ }
+ }
- uploadArtifact.addListener(new Upload.SucceededListener() {
+ /**
+ * Closes this window.
+ */
+ final void closeWindow() {
+ // close the window by removing it from the parent window
+ getParent().removeWindow(this);
+ }
- public void uploadSucceeded(SucceededEvent event) {
+ /**
+ * Imports all local, i.e., that are already in our local OBR, bundles.
+ *
+ * @param artifacts the UI-table with artifacts to install, cannot be <code>null</code>.
+ * @return the imported artifacts, never <code>null</code>.
+ */
+ final List<ArtifactObject> importLocalBundles(final Table artifacts) {
+ final List<ArtifactObject> added = new ArrayList<ArtifactObject>();
+
+ Set<String> selectedItems = (Set<String>) artifacts.getValue();
+ if (selectedItems != null && !selectedItems.isEmpty()) {
+ for (String itemID : selectedItems) {
try {
- URL artifact = m_file.toURI().toURL();
- Item item = uploadedArtifacts.addItem(artifact);
- item.getItemProperty("symbolic name").setValue(
- m_file.getName());
- item.getItemProperty("version").setValue("");
- m_uploadedArtifacts.add(m_file);
+ added.add(importLocalBundle(new URL(m_obrUrl, itemID)));
}
- catch (IOException e) {
- m_main.showNotification(
- "Upload artifact processing failed",
- "<br />Reason: " + e.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Processing of " + m_file.getAbsolutePath()
- + " failed.", e);
+ catch (Exception exception) {
+ Item item = artifacts.getItem(itemID);
+
+ Object symbolicName = item.getItemProperty(ArtifactTable.PROPERTY_SYMBOLIC_NAME).getValue();
+ Object version = item.getItemProperty(ArtifactTable.PROPERTY_VERSION).getValue();
+
+ showErrorNotification("Import artifact failed", "Artifact " + symbolicName + " " + version
+ + "<br />could not be imported into the repository."
+ + "<br />Reason: " + exception.getMessage());
+
+ logError("Import of " + symbolicName + " " + version + " failed.", exception);
}
}
- });
- uploadArtifact.addListener(new Upload.FailedListener() {
- public void uploadFailed(FailedEvent event) {
- m_main.showNotification("Upload artifact failed", "File "
- + event.getFilename()
- + "<br />could not be uploaded to the server.<br />"
- + "Reason: " + event.getReason().getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(
- LogService.LOG_ERROR,
- "Upload of " + event.getFilename() + " size "
- + event.getLength() + " type "
- + event.getMIMEType() + " failed.",
- event.getReason());
- }
- });
+ }
+ return added;
+ }
- layout.addComponent(search);
- layout.addComponent(artifacts);
- layout.addComponent(uploadArtifact);
- layout.addComponent(finalUploadedArtifacts);
+ /**
+ * Import remote bundles.
+ *
+ * @param uploadedArtifacts the list with uploaded artifacts, never <code>null</code>.
+ * @return the list of imported bundles.
+ */
+ final List<ArtifactObject> importRemoteBundles(List<File> uploadedArtifacts) {
+ List<ArtifactObject> added = new ArrayList<ArtifactObject>();
- Button close = new Button("Add", new Button.ClickListener() {
- // inline click-listener
- public void buttonClick(ClickEvent event) {
- List<ArtifactObject> added = new ArrayList<ArtifactObject>();
- // TODO add the selected artifacts
- for (Object id : artifacts.getItemIds()) {
- if (artifacts.isSelected(id)) {
- for (OBREntry e : m_obrList) {
- if (e.getUri().equals(id)) {
- try {
- ArtifactObject ao = importBundle(e);
- added.add(ao);
- }
- catch (Exception e1) {
- m_main.showNotification(
- "Import artifact failed",
- "Artifact "
- + e.getSymbolicName()
- + " "
- + e.getVersion()
- + "<br />could not be imported into the repository.<br />"
- + "Reason: "
- + e1.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Import of " + e.getSymbolicName()
- + " " + e.getVersion()
- + " failed.", e1);
- }
- }
- }
- }
- }
- for (File artifact : m_uploadedArtifacts) {
- try {
- ArtifactObject ao = importBundle(artifact.toURI()
- .toURL());
- added.add(ao);
- }
- catch (Exception e) {
- m_main.showNotification(
- "Import artifact failed",
- "Artifact "
- + artifact.getAbsolutePath()
- + "<br />could not be imported into the repository.<br />"
- + "Reason: " + e.getMessage(),
- Notification.TYPE_ERROR_MESSAGE);
- m_log.log(LogService.LOG_ERROR,
- "Import of " + artifact.getAbsolutePath()
- + " failed.", e);
- }
- finally {
- artifact.delete();
- }
- }
- // close the window by removing it from the parent window
- (AddArtifactWindow.this.getParent())
- .removeWindow(AddArtifactWindow.this);
- // TODO: make a decision here
- // so now we have enough information to show a list of imported
- // artifacts (added)
- // but do we want to show this list or do we just assume the
- // user will see the new
- // artifacts in the left most column? do we also report
- // failures? or only report
- // if there were failures?
+ for (File artifact : uploadedArtifacts) {
+ try {
+ added.add(importRemoteBundle(artifact.toURI().toURL()));
}
- });
- // The components added to the window are actually added to the window's
- // layout; you can use either. Alignments are set using the layout
- layout.addComponent(close);
- layout.setComponentAlignment(close, Alignment.MIDDLE_RIGHT);
- search.focus();
+ catch (Exception exception) {
+ showErrorNotification("Import artifact failed", "Artifact "
+ + artifact.getAbsolutePath()
+ + "<br />could not be imported into the repository.<br />"
+ + "Reason: " + exception.getMessage());
+
+ logError("Import of " + artifact.getAbsolutePath() + " failed.", exception);
+ }
+ finally {
+ artifact.delete();
+ }
+ }
+
+ return added;
+ }
+
+ /**
+ * Shows an error message on screen.
+ *
+ * @param aTitle the title of the error message;
+ * @param aMessage the error message itself.
+ */
+ final void showErrorNotification(final String aTitle, final String aMessage) {
+ showNotification(aTitle, aMessage, Notification.TYPE_ERROR_MESSAGE);
+ }
+
+ /**
+ * Logs a given message at the error level.
+ * <p>If there's no log service present, this method will silently ignore the log statement.</p>
+ *
+ * @param aMessage the message to log.
+ */
+ final void logError(String aMessage) {
+ LogService logger = getLogger();
+ if (logger != null) {
+ logger.log(LogService.LOG_ERROR, aMessage);
+ }
+ }
+
+ /**
+ * Logs a given message + exception at the error level.
+ * <p>If there's no log service present, this method will silently ignore the log statement.</p>
+ *
+ * @param aMessage the message to log;
+ * @param aException the exception to log.
+ */
+ final void logError(String aMessage, Throwable aException) {
+ LogService logger = getLogger();
+ if (logger != null) {
+ logger.log(LogService.LOG_ERROR, aMessage, aException);
+ }
+ }
+
+ /**
+ * @return the artifact repository.
+ */
+ protected abstract ArtifactRepository getArtifactRepository();
+
+ /**
+ * @return the log service.
+ */
+ protected abstract LogService getLogger();
+
+ /**
+ * Converts a given artifact object to an OBR entry.
+ *
+ * @param artifactObject the artifact object to convert;
+ * @param artifactURL the artifact url.
+ * @return an OBR entry instance, never <code>null</code>.
+ */
+ private OBREntry convertToOBREntry(ArtifactObject artifactObject, String artifactURL) {
+ return new OBREntry(artifactObject.getName(), artifactObject.getAttribute(BundleHelper.KEY_VERSION), new File(
+ artifactURL).getName());
}
- public void getBundles(Table table) throws Exception {
+ /**
+ * Gets the bundles.
+ *
+ * @param table the table
+ * @return the bundles
+ * @throws Exception the exception
+ */
+ private void getBundles(Table table) throws Exception {
getBundles(table, m_obrUrl);
}
- public void getBundles(Table table, URL obrBaseUrl) throws Exception {
+ /**
+ * Gets the bundles.
+ *
+ * @param dataSource the datasource to fill;
+ * @param obrBaseUrl the obr base url
+ * @return the bundles
+ * @throws Exception the exception
+ */
+ private void getBundles(Table dataSource, URL obrBaseUrl) throws Exception {
// retrieve the repository.xml as a stream
+ List<OBREntry> obrList = parseOBRRepository(obrBaseUrl);
+
+ // Create a list of filenames from the ArtifactRepository
+ // remove those from the OBR entries we already know
+ obrList.removeAll(getUsedOBRArtifacts(obrBaseUrl));
+
+ if (obrList.isEmpty()) {
+ logError("No new data in OBR.");
+ return;
+ }
+
+ // Create a list of all bundle names
+ for (OBREntry s : obrList) {
+ String uri = s.getUri();
+ String symbolicName = s.getSymbolicName();
+ if (symbolicName == null || symbolicName.length() == 0) {
+ symbolicName = uri;
+ }
+ String version = s.getVersion();
+
+ Item item = dataSource.addItem(uri);
+ item.getItemProperty(ArtifactTable.PROPERTY_SYMBOLIC_NAME).setValue(symbolicName);
+ item.getItemProperty(ArtifactTable.PROPERTY_VERSION).setValue(version);
+ }
+ }
+
+ /**
+ * Builds a list of all OBR artifacts currently in use.
+ *
+ * @param obrBaseUrl the base URL of the OBR, cannot be <code>null</code>.
+ * @return a list of used OBR entries, never <code>null</code>.
+ * @throws IOException in case an artifact repository is not present.
+ */
+ private List<OBREntry> getUsedOBRArtifacts(URL obrBaseUrl) throws IOException {
+ ArtifactRepository artifactRepository = getArtifactRepository();
+ if (artifactRepository == null) {
+ throw new IOException("No artifact repository present!");
+ }
+
+ final String baseURL = obrBaseUrl.toExternalForm();
+
+ List<OBREntry> fromRepository = new ArrayList<OBREntry>();
+
+ List<ArtifactObject> artifactObjects = artifactRepository.get();
+ artifactObjects.addAll(artifactRepository.getResourceProcessors());
+
+ for (ArtifactObject ao : artifactObjects) {
+ String artifactURL = ao.getURL();
+ if (artifactURL.startsWith(baseURL)) {
+ // we now know this artifact comes from the OBR we are querying,
+ // so we are interested.
+ fromRepository.add(convertToOBREntry(ao, artifactURL));
+ }
+ }
+ return fromRepository;
+ }
+
+ /**
+ * Imports a local bundle (already contained in the OBR) bundle.
+ *
+ * @param artifactURL the URL of the artifact to import, cannot be <code>null</code>.
+ * @return the imported artifact object, never <code>null</code>.
+ * @throws IOException in case an I/O exception has occurred.
+ */
+ private ArtifactObject importLocalBundle(URL artifactURL) throws IOException {
+ ArtifactRepository artifactRepository = getArtifactRepository();
+ if (artifactRepository == null) {
+ throw new IOException("No artifact repository present!");
+ }
+ return artifactRepository.importArtifact(artifactURL, false /* upload */);
+ }
+
+ /**
+ * Imports a remote bundle by uploading it to the OBR.
+ *
+ * @param artifactURL the URL of the artifact to import, cannot be <code>null</code>.
+ * @return the imported artifact object, never <code>null</code>.
+ * @throws IOException in case an I/O exception has occurred.
+ */
+ private ArtifactObject importRemoteBundle(URL artifactURL) throws IOException {
+ ArtifactRepository artifactRepository = getArtifactRepository();
+ if (artifactRepository == null) {
+ throw new IOException("No artifact repository present!");
+ }
+ return artifactRepository.importArtifact(artifactURL, true /* upload */);
+ }
+
+ /**
+ * Parses the 'repository.xml' from OBR.
+ *
+ * @param obrBaseUrl the base URL to access the OBR, cannot be <code>null</code>.
+ * @return a list of parsed OBR entries, never <code>null</code>.
+ * @throws XPathExpressionException in case OBR repository is invalid, or incorrect;
+ * @throws IOException in case of problems accessing the 'repository.xml' file.
+ */
+ private List<OBREntry> parseOBRRepository(URL obrBaseUrl) throws XPathExpressionException, IOException {
URL url = null;
try {
- url = new URL(obrBaseUrl, "repository.xml");
+ url = new URL(obrBaseUrl, REPOSITORY_XML);
}
catch (MalformedURLException e) {
- m_log.log(LogService.LOG_ERROR,
- "Error retrieving repository.xml from " + obrBaseUrl);
+ logError("Error retrieving repository.xml from " + obrBaseUrl);
throw e;
}
@@ -393,27 +699,23 @@ class AddArtifactWindow extends Window {
NodeList resources = null;
try {
URLConnection connection = url.openConnection();
- connection.setUseCaches(false); // We always want the newest
- // repository.xml file.
+ // We always want the newest repository.xml file.
+ connection.setUseCaches(false);
input = connection.getInputStream();
try {
XPath xpath = XPathFactory.newInstance().newXPath();
// this XPath expressing will find all 'resource' elements which
// have an attribute 'uri'.
- resources = (NodeList) xpath.evaluate(
- "/repository/resource[@uri]", new InputSource(input),
- XPathConstants.NODESET);
+ resources = (NodeList) xpath.evaluate(XPATH_QUERY, new InputSource(input), XPathConstants.NODESET);
}
catch (XPathExpressionException e) {
- m_log.log(LogService.LOG_ERROR,
- "Error evaluating XPath expression.", e);
+ logError("Error evaluating XPath expression.", e);
throw e;
}
}
catch (IOException e) {
- m_log.log(LogService.LOG_ERROR,
- "Error reading repository metadata.", e);
+ logError("Error reading repository metadata.", e);
throw e;
}
finally {
@@ -427,76 +729,18 @@ class AddArtifactWindow extends Window {
}
}
- m_obrList = new ArrayList<OBREntry>();
+ List<OBREntry> obrList = new ArrayList<OBREntry>();
for (int nResource = 0; nResource < resources.getLength(); nResource++) {
Node resource = resources.item(nResource);
NamedNodeMap attr = resource.getAttributes();
+
String uri = getNamedItemText(attr, "uri");
String symbolicname = getNamedItemText(attr, "symbolicname");
String version = getNamedItemText(attr, "version");
- m_obrList.add(new OBREntry(symbolicname, version, uri));
- }
-
- // Create a list of filenames from the ArtifactRepository
- List<OBREntry> fromRepository = new ArrayList<OBREntry>();
- List<ArtifactObject> artifactObjects = m_artifactRepository.get();
- artifactObjects.addAll(m_artifactRepository.getResourceProcessors());
- for (ArtifactObject ao : artifactObjects) {
- String artifactURL = ao.getURL();
- if (artifactURL.startsWith(obrBaseUrl.toExternalForm())) {
- // we now know this artifact comes from the OBR we are querying,
- // so we are interested.
- fromRepository.add(new OBREntry(ao.getName(), ao
- .getAttribute(BundleHelper.KEY_VERSION), new File(
- artifactURL).getName()));
- }
- }
-
- // remove all urls we already know
- m_obrList.removeAll(fromRepository);
- if (m_obrList.isEmpty()) {
- m_log.log(LogService.LOG_INFO, "No new data in OBR.");
- return;
- }
-
- // Create a list of all bundle names
- for (OBREntry s : m_obrList) {
- String uri = s.getUri();
- String symbolicName = s.getSymbolicName();
- String version = s.getVersion();
- try {
- Item item = table.addItem(uri);
- if (symbolicName == null || symbolicName.length() == 0) {
- item.getItemProperty("symbolic name").setValue(uri);
- }
- else {
- item.getItemProperty("symbolic name")
- .setValue(symbolicName);
- }
- item.getItemProperty("version").setValue(version);
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
- private static String getNamedItemText(NamedNodeMap attr, String name) {
- Node namedItem = attr.getNamedItem(name);
- if (namedItem == null) {
- return null;
+ obrList.add(new OBREntry(symbolicname, version, uri));
}
- else {
- return namedItem.getTextContent();
- }
- }
-
- public ArtifactObject importBundle(OBREntry bundle) throws IOException {
- return m_artifactRepository.importArtifact(
- new URL(m_obrUrl, bundle.getUri()), false);
- }
- public ArtifactObject importBundle(URL artifact) throws IOException {
- return m_artifactRepository.importArtifact(artifact, true);
+ return obrList;
}
}
\ No newline at end of file
Modified: ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java?rev=1300825&r1=1300824&r2=1300825&view=diff
==============================================================================
--- ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java (original)
+++ ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java Thu Mar 15 07:37:19 2012
@@ -1,17 +1,45 @@
+/*
+ * 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.ace.webui.vaadin;
import com.vaadin.ui.Table;
-import com.vaadin.ui.Window;
+/**
+ * Provides a custom table for displaying artifacts by their symbolic name and version.
+ */
public class ArtifactTable extends Table {
- public ArtifactTable(final Window main) {
+
+ public static final String PROPERTY_SYMBOLIC_NAME = "symbolic name";
+ public static final String PROPERTY_VERSION = "version";
+
+ public ArtifactTable() {
super("Artifacts");
- addContainerProperty("symbolic name", String.class, null);
- addContainerProperty("version", String.class, null);
+
+ addContainerProperty(PROPERTY_SYMBOLIC_NAME, String.class, null);
+ addContainerProperty(PROPERTY_VERSION, String.class, null);
+
setSizeFull();
+
setSelectable(true);
setMultiSelect(true);
setImmediate(true);
+
setHeight("15em");
}
}
\ No newline at end of file
Modified: ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java?rev=1300825&r1=1300824&r2=1300825&view=diff
==============================================================================
--- ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java (original)
+++ ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java Thu Mar 15 07:37:19 2012
@@ -56,7 +56,6 @@ import org.apache.ace.test.utils.FileUti
import org.apache.ace.webui.NamedObject;
import org.apache.ace.webui.UIExtensionFactory;
import org.apache.ace.webui.domain.OBREntry;
-import org.apache.ace.webui.vaadin.component.ConfirmationDialog;
import org.apache.ace.webui.vaadin.component.MainActionToolbar;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
@@ -91,7 +90,6 @@ import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.TableTransferable;
import com.vaadin.ui.Window;
-import com.vaadin.ui.Window.Notification;
/*
@@ -148,7 +146,6 @@ public class VaadinClient extends com.va
private List<StatefulGatewayObject> m_targets;
private final Associations m_associations = new Associations();
- private List<OBREntry> m_obrList;
private GridLayout m_grid;
private boolean m_dynamicRelations = true;
@@ -253,16 +250,15 @@ public class VaadinClient extends com.va
}
m_grid = new GridLayout(count, 4);
m_grid.setSpacing(true);
-
- m_grid.setWidth(100, Sizeable.UNITS_PERCENTAGE);
- m_grid.setHeight(100, Sizeable.UNITS_PERCENTAGE);
+ m_grid.setSizeFull();
m_grid.addComponent(createToolbar(), 0, 0, count - 1, 0);
m_artifactsPanel = createArtifactsPanel(m_mainWindow);
m_artifactToolbar = new HorizontalLayout();
- m_artifactToolbar.addComponent(createAddArtifactButton(m_mainWindow));
+ m_artifactToolbar.addComponent(createAddArtifactButton());
+
CheckBox dynamicCheckBox = new CheckBox("Dynamic Links");
dynamicCheckBox.setImmediate(true);
dynamicCheckBox.setValue(Boolean.TRUE);
@@ -907,11 +903,11 @@ public class VaadinClient extends com.va
* @param main Main Window
* @return Button
*/
- private Button createAddArtifactButton(final Window main) {
+ private Button createAddArtifactButton() {
Button button = new Button("Add artifact...");
button.addListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- showAddArtifactDialog(main);
+ showAddArtifactDialog();
}
});
return button;
@@ -1201,17 +1197,27 @@ public class VaadinClient extends com.va
protected abstract RepositoryObject getFromId(String id);
}
- private void showAddArtifactDialog(final Window main) {
- final AddArtifactWindow featureWindow = new AddArtifactWindow(main, m_log, m_sessionDir, m_obrList, m_obrUrl,
- m_artifactRepository);
+ private void showAddArtifactDialog() {
+ final AddArtifactWindow featureWindow = new AddArtifactWindow(m_sessionDir, m_obrUrl) {
+ @Override
+ protected ArtifactRepository getArtifactRepository() {
+ return m_artifactRepository;
+ }
+
+ @Override
+ protected LogService getLogger() {
+ return m_log;
+ }
+ };
+
if (featureWindow.getParent() != null) {
// window is already showing
- main.getWindow().showNotification("Window is already open");
+ getMainWindow().showNotification("Window is already open");
}
else {
// Open the subwindow by adding it to the parent
// window
- main.getWindow().addWindow(featureWindow);
+ getMainWindow().addWindow(featureWindow);
}
}
}