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/07/05 14:10:06 UTC
svn commit: r1357570 [31/34] - in /ace/sandbox/marrs: cnf/ cnf/ext/ cnf/lib/
cnf/releaserepo/ cnf/repo/ cnf/repo/.obrcache/
cnf/repo/.obrcache/http%3A%2F%2Fbundles.bndtools.org.s3.amazonaws.com%2Fcom.jcraft.jsch/
cnf/repo/.obrcache/http%3A%2F%2Fbundles...
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/NamedObject.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/NamedObject.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/NamedObject.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/NamedObject.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,11 @@
+package org.apache.ace.webui;
+
+import org.apache.ace.client.repository.RepositoryObject;
+
+public interface NamedObject {
+ String getName();
+ String getDescription();
+ void setDescription(String description);
+ RepositoryObject getObject();
+ public String getDefinition();
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/UIExtensionFactory.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/UIExtensionFactory.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/UIExtensionFactory.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/UIExtensionFactory.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+import com.vaadin.ui.Component;
+
+/**
+ * Creates components for named extension points in the Vaadin UI. Extension factories
+ * are used throughout the UI to allow other bundles to contribute features.
+ */
+public interface UIExtensionFactory {
+ public static final String EXTENSION_POINT_KEY = "extension_point";
+ public static final String EXTENSION_POINT_VALUE_ARTIFACT = "artifact";
+ public static final String EXTENSION_POINT_VALUE_FEATURE = "feature";
+ public static final String EXTENSION_POINT_VALUE_DISTRIBUTION = "distribution";
+ public static final String EXTENSION_POINT_VALUE_TARGET = "target";
+
+ /**
+ * Creates a UI component for use in the extension point. The contents of the
+ * context are extension-point dependent.
+ */
+ Component create(Map<String, Object> context);
+}
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedArtifactObject.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedArtifactObject.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedArtifactObject.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedArtifactObject.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,51 @@
+/*
+ * 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.domain;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.webui.NamedObject;
+
+public class NamedArtifactObject implements NamedObject {
+ private final ArtifactObject m_target;
+
+ public NamedArtifactObject(ArtifactObject target) {
+ m_target = target;
+ }
+
+ public String getName() {
+ return m_target.getName();
+ }
+
+ public String getDescription() {
+ return m_target.getDescription();
+ }
+
+ public void setDescription(String description) {
+ m_target.setDescription(description);
+ }
+
+ public RepositoryObject getObject() {
+ return m_target;
+ }
+
+ public String getDefinition() {
+ return m_target.getDefinition();
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedDistributionObject.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedDistributionObject.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedDistributionObject.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedDistributionObject.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,51 @@
+/*
+ * 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.domain;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.apache.ace.webui.NamedObject;
+
+public class NamedDistributionObject implements NamedObject {
+ private final DistributionObject m_target;
+
+ public NamedDistributionObject(DistributionObject target) {
+ m_target = target;
+ }
+
+ public String getName() {
+ return m_target.getName();
+ }
+
+ public String getDescription() {
+ return m_target.getDescription();
+ }
+
+ public void setDescription(String description) {
+ m_target.setDescription(description);
+ }
+
+ public RepositoryObject getObject() {
+ return m_target;
+ }
+
+ public String getDefinition() {
+ return m_target.getDefinition();
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedFeatureObject.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedFeatureObject.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedFeatureObject.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedFeatureObject.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,51 @@
+/*
+ * 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.domain;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.webui.NamedObject;
+
+public class NamedFeatureObject implements NamedObject {
+ private final FeatureObject m_target;
+
+ public NamedFeatureObject(FeatureObject target) {
+ m_target = target;
+ }
+
+ public String getName() {
+ return m_target.getName();
+ }
+
+ public String getDescription() {
+ return m_target.getDescription();
+ }
+
+ public void setDescription(String description) {
+ m_target.setDescription(description);
+ }
+
+ public RepositoryObject getObject() {
+ return m_target;
+ }
+
+ public String getDefinition() {
+ return m_target.getDefinition();
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedTargetObject.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedTargetObject.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedTargetObject.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/NamedTargetObject.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,62 @@
+/*
+ * 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.domain;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.TargetObject;
+import org.apache.ace.client.repository.stateful.StatefulTargetObject;
+import org.apache.ace.webui.NamedObject;
+
+public class NamedTargetObject implements NamedObject {
+ private final RepositoryObject m_target;
+
+ public NamedTargetObject(StatefulTargetObject target) {
+ m_target = target;
+ }
+
+ public NamedTargetObject(TargetObject target) {
+ m_target = target;
+ }
+
+ public String getName() {
+ if (m_target instanceof StatefulTargetObject) {
+ return ((StatefulTargetObject) m_target).getID();
+ }
+ else if (m_target instanceof TargetObject) {
+ return ((TargetObject) m_target).getID();
+ }
+ return null;
+ }
+
+ public String getDescription() {
+ return "";
+ }
+
+ public void setDescription(String description) {
+ throw new IllegalArgumentException();
+ }
+
+ public RepositoryObject getObject() {
+ return m_target;
+ }
+
+ public String getDefinition() {
+ return m_target.getDefinition();
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/OBREntry.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/OBREntry.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/OBREntry.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/domain/OBREntry.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,53 @@
+/*
+ * 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.domain;
+
+public class OBREntry {
+ private final String m_symbolicName;
+ private final String m_version;
+ private final String m_uri;
+
+ public OBREntry(String symbolicName, String version, String uri) {
+ m_symbolicName = symbolicName;
+ m_version = version;
+ m_uri = uri;
+ }
+
+ public String getVersion() {
+ return m_version;
+ }
+
+ public String getSymbolicName() {
+ return m_symbolicName;
+ }
+
+ public String getUri() {
+ return m_uri;
+ }
+
+ @Override
+ public int hashCode() {
+ return m_uri.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return m_uri.equals(((OBREntry) obj).m_uri);
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/packageinfo
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/packageinfo?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/packageinfo (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/packageinfo Thu Jul 5 12:09:30 2012
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Activator.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Activator.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Activator.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Activator.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,88 @@
+/*
+ * 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 java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.Servlet;
+
+import org.apache.ace.client.repository.stateful.StatefulTargetObject;
+import org.apache.ace.webui.NamedObject;
+import org.apache.ace.webui.UIExtensionFactory;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.http.HttpService;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalLayout;
+
+public class Activator extends DependencyActivatorBase {
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws Exception {
+ manager.add(createComponent()
+ .setImplementation(VaadinResourceHandler.class)
+ .add(createServiceDependency()
+ .setService(HttpService.class)
+ .setRequired(true)
+ )
+ );
+ // register the main application for the ACE UI client
+ manager.add(createComponent()
+ .setInterface(Servlet.class.getName(), null)
+ .setImplementation(VaadinServlet.class)
+ .add(createConfigurationDependency()
+ .setPid(VaadinServlet.PID).setPropagate(true))
+ );
+
+ Properties props = new Properties();
+ props.put(UIExtensionFactory.EXTENSION_POINT_KEY, UIExtensionFactory.EXTENSION_POINT_VALUE_TARGET);
+ props.put(Constants.SERVICE_RANKING, Integer.valueOf(100));
+
+ // shows off components that are contributed by extensions
+ manager.add(createComponent()
+ .setInterface(UIExtensionFactory.class.getName(), props)
+ .setImplementation(new UIExtensionFactory() {
+ public Component create(Map<String, Object> context) {
+ VerticalLayout vl = new VerticalLayout();
+ vl.setCaption("Info");
+ final NamedObject namedObject = (NamedObject) context.get("object");
+ final StatefulTargetObject target = (StatefulTargetObject) namedObject.getObject();
+ Label info = new Label(
+ "Target ID : " + namedObject.getName() + "\n" +
+ "Installed version : " + (target.getLastInstallVersion() == null ? "(none)" : target.getLastInstallVersion()) + "\n" +
+ "Available version : " + target.getCurrentVersion() + "\n" +
+ "Store state : " + target.getStoreState() + "\n" +
+ "Provisioning state : " + target.getProvisioningState() + "\n" +
+ "Registration state : " + target.getRegistrationState());
+ info.setContentMode(Label.CONTENT_PREFORMATTED);
+ vl.addComponent(info);
+ return vl;
+ }
+ })
+ );
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ }
+}
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AddArtifactWindow.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AddArtifactWindow.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AddArtifactWindow.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AddArtifactWindow.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,764 @@
+/*
+ * 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 java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+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;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.ace.client.repository.helper.bundle.BundleHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.webui.domain.OBREntry;
+import org.osgi.service.log.LogService;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+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;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.terminal.StreamVariable;
+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;
+
+/**
+ * Provides a dialog for uploading new artifacts to ACE, or selecting existing artifacts from the repository.
+ */
+abstract class AddArtifactWindow extends Window {
+
+ /**
+ * 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);
+ }
+ }
+ }
+
+ /*
+ * @see com.vaadin.event.dd.DropHandler#getAcceptCriterion()
+ */
+ public AcceptCriterion getAcceptCriterion() {
+ // TODO only accept .jar files ?
+ return AcceptAll.get();
+ }
+ }
+
+ /**
+ * 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);
+
+ try {
+ artifactUploaded(m_file);
+ }
+ finally {
+ m_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;
+ }
+
+ /**
+ * 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 {
+ closable.close();
+ }
+ catch (IOException e) {
+ // Best effort; nothing we can (or want) do about this...
+ }
+ }
+ }
+ }
+
+ private static final String REPOSITORY_XML = "repository.xml";
+ private static final String XPATH_QUERY = "/repository/resource[@uri]";
+
+ private final File m_sessionDir;
+ private final URL m_obrUrl;
+
+ private final List<File> m_uploadedArtifacts = new ArrayList<File>();
+ private final Button m_searchButton;
+ private final Button m_closeButton;
+ private final Table m_artifactsTable;
+
+ /**
+ * 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");
+
+ m_artifactsTable = new ArtifactTable();
+ m_artifactsTable.setCaption("Artifacts in repository");
+
+ final IndexedContainer dataSource = (IndexedContainer) m_artifactsTable.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();
+
+ Item item = uploadedArtifacts.addItem(artifact);
+ item.getItemProperty(ArtifactTable.PROPERTY_SYMBOLIC_NAME).setValue(uploadedArtifact.getName());
+ item.getItemProperty(ArtifactTable.PROPERTY_VERSION).setValue("");
+
+ m_uploadedArtifacts.add(uploadedArtifact);
+ }
+ catch (MalformedURLException e) {
+ showErrorNotification("Upload artifact processing failed", "<br />Reason: " + e.getMessage());
+ logError("Processing of " + uploadedArtifact + " failed.", e);
+ }
+ }
+
+ @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.");
+ }
+ };
+
+ 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));
+
+ addListener(new Window.CloseListener() {
+ public void windowClose(CloseEvent e) {
+ for (File artifact : m_uploadedArtifacts) {
+ artifact.delete();
+ }
+ }
+ });
+
+ 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(m_artifactsTable);
+ // 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(m_artifactsTable);
+ 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);
+
+ 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();
+ }
+ }
+
+ /**
+ * Shows this dialog on the parent window.
+ *
+ * @param parent the parent for this window, cannot be <code>null</code>.
+ */
+ public final void showWindow(Window parent) {
+ try {
+ // Fill the artifacts table with the data from the OBR...
+ getBundles(m_artifactsTable);
+
+ parent.addWindow(this);
+ }
+ catch (Exception e) {
+ // We've not yet added this window to the given parent, so we cannot use #showErrorNotification here...
+ parent.showNotification("Failed to retrieve OBR repository!", "Reason: <br/>" + e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
+ logError("Failed to retrieve OBR repository!", e);
+ }
+ }
+
+ /**
+ * Closes this window.
+ */
+ final void closeWindow() {
+ // close the window by removing it from the parent window
+ getParent().removeWindow(this);
+ }
+
+ /**
+ * 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 {
+ added.add(importLocalBundle(new URL(m_obrUrl, itemID)));
+ }
+ 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);
+ }
+ }
+ }
+ return added;
+ }
+
+ /**
+ * 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>();
+
+ for (File artifact : uploadedArtifacts) {
+ try {
+ added.add(importRemoteBundle(artifact.toURI().toURL()));
+ }
+ catch (Exception exception) {
+ showErrorNotification("Import artifact failed", "<br/>Artifact '"
+ + artifact.getName()
+ + "' 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) {
+ getParent().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();
+
+ /**
+ * @param url the URL to connect to, cannot be <code>null</code>.
+ * @return a valid {@link URLConnection} instance, never <code>null</code>.
+ */
+ protected abstract URLConnection openConnection(URL url) throws IOException;
+
+ /**
+ * 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());
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+ catch (MalformedURLException e) {
+ logError("Error retrieving repository.xml from " + obrBaseUrl);
+ throw e;
+ }
+
+ InputStream input = null;
+ NodeList resources = null;
+ try {
+ URLConnection connection = openConnection(url);
+ // 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(XPATH_QUERY, new InputSource(input), XPathConstants.NODESET);
+ }
+ catch (XPathExpressionException e) {
+ logError("Error evaluating XPath expression.", e);
+ throw e;
+ }
+ }
+ catch (IOException e) {
+ logError("Error reading repository metadata.", e);
+ throw e;
+ }
+ finally {
+ if (input != null) {
+ try {
+ input.close();
+ }
+ catch (IOException e) {
+ // too bad, no worries.
+ }
+ }
+ }
+
+ 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");
+
+ obrList.add(new OBREntry(symbolicname, version, uri));
+ }
+
+ return obrList;
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/ArtifactTable.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/ArtifactTable.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/ArtifactTable.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/ArtifactTable.java Thu Jul 5 12:09:30 2012
@@ -0,0 +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;
+
+/**
+ * Provides a custom table for displaying artifacts by their symbolic name and version.
+ */
+public class ArtifactTable extends Table {
+
+ public static final String PROPERTY_SYMBOLIC_NAME = "symbolic name";
+ public static final String PROPERTY_VERSION = "version";
+
+ public ArtifactTable() {
+ super("Artifacts");
+
+ 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
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AssociationRemover.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AssociationRemover.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AssociationRemover.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/AssociationRemover.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,46 @@
+/*
+ * 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 org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
+import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+
+/**
+ * Defines methods for removing associations.
+ */
+public interface AssociationRemover {
+
+ /**
+ * @param association
+ */
+ void removeAssociation(Artifact2FeatureAssociation association);
+
+ /**
+ * @param association
+ */
+ void removeAssociation(Feature2DistributionAssociation association);
+
+ /**
+ * @param association
+ */
+ void removeAssociation(Distribution2TargetAssociation association);
+
+}
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Associations.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Associations.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Associations.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/Associations.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,241 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ace.client.repository.ObjectRepository;
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.TargetObject;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.apache.ace.client.repository.stateful.StatefulTargetObject;
+import org.apache.ace.webui.NamedObject;
+import org.apache.ace.webui.domain.NamedArtifactObject;
+import org.apache.ace.webui.domain.NamedDistributionObject;
+import org.apache.ace.webui.domain.NamedFeatureObject;
+import org.apache.ace.webui.domain.NamedTargetObject;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.CellStyleGenerator;
+
+public class Associations {
+ private List<RepositoryObject> m_associatedItems = new ArrayList<RepositoryObject>();
+ private List<RepositoryObject> m_relatedItems = new ArrayList<RepositoryObject>();
+ private Table m_activeTable;
+ private Set<?> m_activeSelection;
+ private SelectionListener m_activeSelectionListener;
+
+ public void removeAssociatedItem(RepositoryObject item) {
+ m_associatedItems.remove(item);
+ }
+
+ public void clear() {
+ m_associatedItems.clear();
+ m_relatedItems.clear();
+ }
+
+ public boolean isActiveTable(Table table) {
+ return (m_activeTable != null) ? m_activeTable.equals(table) : false;
+ }
+
+ public Set<?> getActiveSelection() {
+ return m_activeSelection;
+ }
+
+ public RepositoryObject lookupInActiveSelection(Object item) {
+ return m_activeSelectionListener.lookup(item);
+ }
+
+ public void addAssociatedItems(List items) {
+ m_associatedItems.addAll(items);
+ }
+
+ public void addRelatedItems(List items) {
+ m_relatedItems.addAll(items);
+ }
+
+ public CellStyleGenerator createCellStyleGenerator() {
+ return new CellStyleGenerator() {
+ public String getStyle(Object itemId, Object propertyId) {
+ if (propertyId == null) {
+ // no propertyId, styling row
+ for (RepositoryObject o : m_associatedItems) {
+ if (equals(itemId, o)) {
+ return "associated";
+ }
+ }
+ for (RepositoryObject o : m_relatedItems) {
+ if (equals(itemId, o)) {
+ return "related";
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean equals(Object itemId, RepositoryObject object) {
+ return (getNamedObject(object).getDefinition().equals(itemId));
+ }
+ };
+ }
+
+ public NamedObject getNamedObject(RepositoryObject object) {
+ if (object instanceof ArtifactObject) {
+ return new NamedArtifactObject((ArtifactObject) object);
+ }
+ else if (object instanceof FeatureObject) {
+ return new NamedFeatureObject((FeatureObject) object);
+ }
+ else if (object instanceof DistributionObject) {
+ return new NamedDistributionObject((DistributionObject) object);
+ }
+ else if (object instanceof StatefulTargetObject) {
+ return new NamedTargetObject((StatefulTargetObject) object);
+ }
+ else if (object instanceof TargetObject) {
+ return new NamedTargetObject((TargetObject) object);
+ }
+ return null;
+ }
+
+ /**
+ * Helper method to find all related {@link RepositoryObject}s in a given 'direction'
+ */
+ private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(FROM from,
+ Class<TO> toClass) {
+ // if the SGO is not backed by a GO yet, this will cause an exception
+ return from.getAssociations(toClass);
+ }
+
+ /**
+ * Helper method to find all related {@link RepositoryObject}s in a given 'direction', starting with a list of objects
+ */
+ private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(List<FROM> from,
+ Class<TO> toClass) {
+ List<TO> result = new ArrayList<TO>();
+ for (RepositoryObject o : from) {
+ result.addAll(getRelated(o, toClass));
+ }
+ return result;
+ }
+
+ public class SelectionListener implements Table.ValueChangeListener {
+ private final Table m_table;
+ private final Table[] m_tablesToRefresh;
+ private final ObjectRepository<? extends RepositoryObject> m_repository;
+ private final Class[] m_left;
+ private final Class[] m_right;
+
+ public SelectionListener(final Table table, final ObjectRepository<? extends RepositoryObject> repository,
+ final Class[] left, final Class[] right, final Table[] tablesToRefresh) {
+ m_table = table;
+ m_repository = repository;
+ m_left = left;
+ m_right = right;
+ m_tablesToRefresh = tablesToRefresh;
+ }
+
+ public void valueChange(ValueChangeEvent event) {
+
+ if (m_activeSelection != null && m_activeTable != null) {
+ if (!m_activeTable.equals(m_table)) {
+ for (Object val : m_activeSelection) {
+ m_activeTable.unselect(val);
+ }
+ m_table.requestRepaint();
+ }
+ }
+
+ m_activeSelectionListener = SelectionListener.this;
+
+ // set the active table
+ m_activeTable = m_table;
+
+ // in multiselect mode, a Set of itemIds is returned,
+ // in singleselect mode the itemId is returned directly
+ Set<?> value = (Set<?>) event.getProperty().getValue();
+
+ // remember the active selection too
+ m_activeSelection = value;
+
+ if (value != null) {
+ clear();
+ for (Object val : value) {
+ RepositoryObject lo = lookup(val);
+ if (lo != null) {
+ List related = null;
+ for (int i = 0; i < m_left.length; i++) {
+ if (i == 0) {
+ related = getRelated(lo, m_left[i]);
+ m_associatedItems.addAll(related);
+ }
+ else {
+ related = getRelated(related, m_left[i]);
+ m_relatedItems.addAll(related);
+ }
+ }
+ for (int i = 0; i < m_right.length; i++) {
+ if (i == 0) {
+ related = getRelated(lo, m_right[i]);
+ m_associatedItems.addAll(related);
+ }
+ else {
+ related = getRelated(related, m_right[i]);
+ m_relatedItems.addAll(related);
+ }
+ }
+ }
+
+ for (Table t : m_tablesToRefresh) {
+ t.requestRepaint();
+ }
+ }
+ }
+ }
+
+ public RepositoryObject lookup(Object value) {
+ RepositoryObject object = null;
+ if (value instanceof String) {
+ object = m_repository.get((String) value);
+ if (object instanceof StatefulTargetObject) {
+ StatefulTargetObject sgo = (StatefulTargetObject) object;
+ if (sgo.isRegistered()) {
+ object = sgo.getTargetObject();
+ }
+ else {
+ object = null;
+ }
+ }
+ }
+ return object;
+ }
+
+ }
+
+ public SelectionListener createSelectionListener(final Table table,
+ final ObjectRepository<? extends RepositoryObject> repository, final Class[] left, final Class[] right,
+ final Table[] tablesToRefresh) {
+ return new SelectionListener(table, repository, left, right, tablesToRefresh);
+ }
+}
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/EditWindow.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/EditWindow.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/EditWindow.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/EditWindow.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,178 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ace.webui.NamedObject;
+import org.apache.ace.webui.UIExtensionFactory;
+
+import com.vaadin.event.ShortcutAction.KeyCode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+/**
+ * Provides a generic editor for repository objects.
+ */
+public abstract class EditWindow extends Window {
+
+ protected final TextField m_name;
+ protected final TextField m_description;
+
+ /**
+ * @param object
+ * @param factories
+ */
+ public EditWindow(String caption, NamedObject object, List<UIExtensionFactory> factories) {
+ setModal(true);
+ setWidth("50em");
+ setCaption(caption);
+
+ m_name = new TextField("Name", object.getName());
+ m_name.setReadOnly(true);
+ m_name.setWidth("100%");
+
+ m_description = new TextField("Description", object.getDescription());
+ m_description.setWidth("100%");
+
+ initDialog(object, factories);
+ }
+
+ /**
+ * Shows this dialog on screen.
+ *
+ * @param window the parent window to show this dialog on, cannot be <code>null</code>.
+ */
+ public void show(Window parent) {
+ if (getParent() != null) {
+ // window is already showing
+ parent.showNotification("Window is already open!");
+ }
+ else {
+ parent.addWindow(this);
+ }
+ setRelevantFocus();
+ }
+
+ /**
+ * Closes this dialog by removing it from the parent window.
+ */
+ protected void closeDialog() {
+ // close the window by removing it from the parent window
+ getParent().removeWindow(this);
+ }
+
+ /**
+ * Called when the {@link #onOk(String, String)} method failed with an exception.
+ *
+ * @param e the exception to handle, never <code>null</code>.
+ */
+ protected abstract void handleError(Exception e);
+
+ /**
+ * @param object
+ * @param factories
+ */
+ protected void initDialog(final NamedObject object, List<UIExtensionFactory> factories) {
+ VerticalLayout fields = new VerticalLayout();
+ fields.setSpacing(true);
+ fields.addComponent(m_name);
+ fields.addComponent(m_description);
+
+ TabSheet tabs = new TabSheet();
+ tabs.setHeight("350px");
+ tabs.setWidth("100%");
+ tabs.setVisible(!factories.isEmpty());
+
+ Map<String, Object> context = new HashMap<String, Object>();
+ context.put("object", object);
+
+ for (UIExtensionFactory factory : factories) {
+ try {
+ tabs.addTab(factory.create(context));
+ }
+ catch (Throwable ex) {
+ // We ignore extension factories that throw exceptions
+ // TODO: log this or something
+ ex.printStackTrace();
+ }
+ }
+
+ Button okButton = new Button("Ok", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ try {
+ onOk((String) m_name.getValue(), (String) m_description.getValue());
+ closeDialog();
+ }
+ catch (Exception e) {
+ handleError(e);
+ }
+ }
+ });
+ // Allow enter to be used to close this dialog with enter directly...
+ okButton.setClickShortcut(KeyCode.ENTER);
+ okButton.addStyleName("primary");
+
+ Button cancelButton = new Button("Cancel", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ closeDialog();
+ }
+ });
+
+ HorizontalLayout buttonBar = new HorizontalLayout();
+ buttonBar.setSpacing(true);
+ buttonBar.addComponent(okButton);
+ buttonBar.addComponent(cancelButton);
+
+ VerticalLayout layout = (VerticalLayout) getContent();
+ layout.setMargin(true);
+ layout.setSpacing(true);
+ layout.addComponent(fields);
+ layout.addComponent(tabs);
+ layout.addComponent(buttonBar);
+
+ // 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.setComponentAlignment(buttonBar, Alignment.BOTTOM_RIGHT);
+ }
+
+ /**
+ * Called when the user acknowledges this window by pressing Ok.
+ *
+ * @param name the value of the name field;
+ * @param description the value of the description field.
+ * @throws Exception in case the creation failed.
+ */
+ protected abstract void onOk(String name, String description) throws Exception;
+
+ /**
+ * Sets the focus to the name field.
+ */
+ private void setRelevantFocus() {
+ m_name.focus();
+ }
+}
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/GenericAddWindow.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/GenericAddWindow.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/GenericAddWindow.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/GenericAddWindow.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,142 @@
+/*
+ * 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.event.ShortcutAction.KeyCode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+public abstract class GenericAddWindow extends Window {
+
+ protected final TextField m_name;
+ protected final TextField m_description;
+
+ public GenericAddWindow(String caption) {
+ setModal(true);
+ setWidth("15em");
+ setCaption(caption);
+
+ m_name = new TextField("Name");
+ m_name.setWidth("100%");
+
+ m_description = new TextField("Description");
+ m_description.setWidth("100%");
+
+ initDialog();
+ }
+
+ /**
+ * Shows this dialog on screen.
+ *
+ * @param window the parent window to show this dialog on, cannot be <code>null</code>.
+ */
+ public void show(final Window window) {
+ if (getParent() != null) {
+ // window is already showing
+ window.showNotification("Window is already open");
+ }
+ else {
+ // Open the subwindow by adding it to the parent window
+ window.addWindow(this);
+ }
+ setRelevantFocus();
+ }
+
+ /**
+ * Closes this dialog by removing it from the parent window.
+ */
+ protected void closeDialog() {
+ // close the window by removing it from the parent window
+ getParent().removeWindow(this);
+ }
+
+ /**
+ * Called when the {@link #onOk(String, String)} method failed with an exception.
+ *
+ * @param e the exception to handle, never <code>null</code>.
+ */
+ protected abstract void handleError(Exception e);
+
+ /**
+ * Initializes this dialog by placing all components on it.
+ */
+ protected void initDialog() {
+ VerticalLayout fields = new VerticalLayout();
+ fields.setSpacing(true);
+ fields.addComponent(m_name);
+ fields.addComponent(m_description);
+
+ Button okButton = new Button("Ok", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ try {
+ onOk((String) m_name.getValue(), (String) m_description.getValue());
+ closeDialog();
+ }
+ catch (Exception e) {
+ handleError(e);
+ }
+ }
+ });
+ // Allow enter to be used to close this dialog with enter directly...
+ okButton.setClickShortcut(KeyCode.ENTER);
+ okButton.addStyleName("primary");
+
+ Button cancelButton = new Button("Cancel", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ closeDialog();
+ }
+ });
+
+ HorizontalLayout buttonBar = new HorizontalLayout();
+ buttonBar.setSpacing(true);
+ buttonBar.addComponent(okButton);
+ buttonBar.addComponent(cancelButton);
+
+ VerticalLayout layout = (VerticalLayout) getContent();
+ layout.setMargin(true);
+ layout.setSpacing(true);
+ layout.addComponent(fields);
+ layout.addComponent(buttonBar);
+
+ // 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.setComponentAlignment(buttonBar, Alignment.BOTTOM_RIGHT);
+ }
+
+ /**
+ * Called when the user acknowledges this window by pressing Ok.
+ *
+ * @param name the value of the name field;
+ * @param description the value of the description field.
+ * @throws Exception in case the creation failed.
+ */
+ protected abstract void onOk(String name, String description) throws Exception;
+
+ /**
+ * Sets the focus to the name field.
+ */
+ private void setRelevantFocus() {
+ m_name.focus();
+ }
+}
\ No newline at end of file
Added: ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/LoginWindow.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/LoginWindow.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/LoginWindow.java (added)
+++ ace/sandbox/marrs/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/LoginWindow.java Thu Jul 5 12:09:30 2012
@@ -0,0 +1,127 @@
+/*
+ * 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 org.osgi.service.log.LogService;
+
+import com.vaadin.event.ShortcutAction.KeyCode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.PasswordField;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+/**
+ * Provides a simple login dialog.
+ */
+public class LoginWindow extends Window {
+
+ public interface LoginFunction {
+ boolean login(String name, String password);
+ }
+
+ private volatile LogService m_log;
+
+ private TextField m_name;
+ private PasswordField m_password;
+ private Button m_loginButton;
+ private LoginFunction m_loginFunction;
+
+ public LoginWindow(final LogService log, final LoginFunction loginFunction) {
+ super("Apache ACE Login");
+
+ m_log = log;
+ m_loginFunction = loginFunction;
+
+ setResizable(false);
+ setClosable(false);
+ setModal(true);
+ setWidth("15em");
+
+ m_name = new TextField("Name", "");
+ m_name.setImmediate(true);
+
+ m_password = new PasswordField("Password", "");
+ m_password.setImmediate(true);
+
+ m_loginButton = new Button("Login");
+ m_loginButton.setImmediate(true);
+ // Allow enter to be used to login directly...
+ m_loginButton.setClickShortcut(KeyCode.ENTER);
+ // Highlight this button as the default one...
+ m_loginButton.addStyleName("primary");
+
+ m_loginButton.addListener(new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ final Button button = event.getButton();
+ button.setEnabled(false);
+
+ try {
+ String username = (String) m_name.getValue();
+ String password = (String) m_password.getValue();
+
+ if (m_loginFunction.login(username, password)) {
+ m_log.log(LogService.LOG_INFO, "Apache Ace WebUI succesfull login by user: " + username);
+
+ closeWindow();
+ }
+ else {
+ m_log.log(LogService.LOG_WARNING, "Apache Ace WebUI invalid username or password entered.");
+
+ getParent().showNotification("Invalid username or password!");
+ setRelevantFocus();
+ }
+ }
+ finally {
+ button.setEnabled(true);
+ }
+ }
+ });
+
+ final VerticalLayout content = (VerticalLayout) getContent();
+ content.setSpacing(true);
+ content.setMargin(true);
+ content.setSizeFull();
+
+ content.addComponent(m_name);
+ content.addComponent(m_password);
+ content.addComponent(m_loginButton);
+
+ content.setComponentAlignment(m_loginButton, Alignment.BOTTOM_CENTER);
+
+ setRelevantFocus();
+ }
+
+ /**
+ * Gives the username field the current focus.
+ */
+ void setRelevantFocus() {
+ m_name.focus();
+ m_name.selectAll();
+ }
+
+ /**
+ * Closes this login window.
+ */
+ public void closeWindow() {
+ getParent().removeWindow(this);
+ }
+}
\ No newline at end of file