Author: jawi
Date: Tue Apr 10 08:30:24 2012
New Revision: 1311629
URL: http://svn.apache.org/viewvc?rev=1311629&view=rev
Log:
ACE-219: verifier sometimes shows empty popup due to missing deployment packages. Now it clearly
states this. Also cleaned up the code a bit.
Added:
ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java
(with props)
Modified:
ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/ACEVerifierExtension.java
Modified: ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/ACEVerifierExtension.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/ACEVerifierExtension.java?rev=1311629&r1=1311628&r2=1311629&view=diff
==============================================================================
--- ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/ACEVerifierExtension.java
(original)
+++ ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/ACEVerifierExtension.java
Tue Apr 10 08:30:24 2012
@@ -19,20 +19,22 @@
package org.apache.ace.deployment.verifier.ui;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.object.DeploymentArtifact;
import org.apache.ace.client.repository.object.DeploymentVersionObject;
-import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
import org.apache.ace.client.repository.stateful.StatefulTargetObject;
import org.apache.ace.deployment.verifier.VerifierService;
@@ -50,183 +52,347 @@ import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
-import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
import com.vaadin.ui.PopupView;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.VerticalLayout;
public class ACEVerifierExtension implements UIExtensionFactory {
- volatile VerifierService m_verifier;
- volatile DeploymentVersionRepository m_repo;
+ /**
+ *
+ */
+ final class ManifestArea extends VerticalLayout implements Property.ValueChangeListener,
Button.ClickListener {
+ private final String m_id;
+ private final TextArea m_editor;
+ private final Label m_plainText;
+ private final StatefulTargetObject m_object;
+ private final PopupView m_popup;
+
+ public ManifestArea(String id, String initialText, StatefulTargetObject object) {
+ setWidth("100%");
+
+ m_id = id;
+ m_object = object;
+
+ m_editor = new TextArea(null, initialText);
+ m_editor.setRows(15);
+ m_editor.addListener(this);
+ m_editor.setImmediate(true);
+ m_editor.setWidth("100%");
+ m_editor.setHeight("70%");
+
+ m_plainText = new Label();
+ m_plainText.setContentMode(Label.CONTENT_XHTML);
+ m_plainText.setImmediate(true);
+ m_plainText.setSizeFull();
+
+ Panel panel = new Panel();
+ panel.setCaption("Verification result");
+ panel.getContent().addComponent(m_plainText);
+ panel.setWidth("800px");
+ panel.setHeight("300px");
+
+ m_popup = new PopupView("Result", panel);
+ m_popup.setCaption("Verification result");
+ m_popup.setHideOnMouseOut(false);
+ m_popup.setVisible(false);
+
+ Button verify = new Button("Verify", this);
+
+ addComponent(m_editor);
+ addComponent(verify);
+ addComponent(m_popup);
+ }
+
+ public void buttonClick(ClickEvent event) {
+ if (m_popup.isPopupVisible()) {
+ m_popup.setPopupVisible(false);
+ }
+
+ String output;
+ try {
+ String manifest = m_editor.getValue().toString();
+ output = verify(m_id, manifest);
+ }
+ catch (Exception e) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+ output = baos.toString();
+ }
+
+ m_plainText.setValue(output);
+
+ m_popup.setVisible(true);
+ m_popup.setPopupVisible(true);
+ }
+
+ public void valueChange(ValueChangeEvent event) {
+ String text = (String) m_editor.getValue();
+
+ if (text != null) {
+ m_object.addAttribute("manifest", text);
+ }
+ }
+ }
+
+ private volatile VerifierService m_verifier;
+ private volatile DeploymentVersionRepository m_repo;
+
+ /**
+ * {@inheritDoc}
+ */
public Component create(Map<String, Object> context) {
RepositoryObject object = getRepositoryObjectFromContext(context);
+
+ Component content = new Label("This target is not yet registered, so it can not verify
anything.");
if (object instanceof StatefulTargetObject) {
StatefulTargetObject statefulTarget = (StatefulTargetObject) object;
if (statefulTarget.isRegistered()) {
- String id = object.getAttribute(TargetObject.KEY_ID);
- return new ManifestArea(id, (object.getAttribute("manifest") == null) ? Constants.BUNDLE_MANIFESTVERSION
+ ": " + "2" + "\n" + Constants.BUNDLE_SYMBOLICNAME + ": " + "org.apache.felix.framework"
+ "\n" + Constants.EXPORT_PACKAGE + ": " + VerifierService.SYSTEM_PACKAGES + "," + VerifierService.JRE_1_6_PACKAGES
+ "," + "org.osgi.service.cm;version=1.2,org.osgi.service.metatype;version=1.1.1,org.osgi.service.cm;
version=1.3.0,org.osgi.service.deploymentadmin.spi; version=1.0.1,org.osgi.service.deploymentadmin;
version=1.1.0" + "\n" : object.getAttribute("manifest"), object);
+ content = new ManifestArea(statefulTarget.getID(), getManifest(statefulTarget),
statefulTarget);
}
}
+
VerticalLayout result = new VerticalLayout();
- result.setCaption("VerifyResolve");
- result.addComponent(new Label("This target is not yet registered, so it can not verify
anything."));
+ result.setMargin(true);
+ result.setCaption("Verify/resolve");
+ result.addComponent(content);
+
return result;
}
+ /**
+ * Performs the actual verification.
+ */
+ final String verify(String targetId, String manifestText) throws Exception {
+ DeploymentVersionObject version = m_repo.getMostRecentDeploymentVersion(targetId);
+ if (version == null) {
+ return "No deployment version available to verify.";
+ }
+
+ VerificationResult result = new VerificationResult();
+ Map<String, String> manifestMap = getManifestEntries(manifestText);
+
+ VerifyEnvironment env = createVerifyEnvironment(manifestMap, result);
+
+ // Add the main entry...
+ result.addBundle(env, manifestMap);
+
+ processArtifacts(version.getDeploymentArtifacts(), env, result);
+
+ StringBuilder sb = new StringBuilder();
+ if (result.hasCustomizers()) {
+ if (!result.allCustomizerMatch()) {
+ sb.append("<p><b>Not all bundle customizers match!</b><br/>");
+ sb.append("Provided = ").append(result.getCustomizers().toString()).append("<br/>");
+ sb.append("Required = ").append(result.getProcessors().toString()).append(".</p>");
+ }
+ else {
+ sb.append("<p>All bundle customizers match!</p>");
+ }
+ }
+
+ boolean resolves = env.verifyResolve(result.getBundles(), null, null);
+ if (resolves) {
+ sb.append("<p>Deployment package resolves.<br/>");
+ }
+ else {
+ sb.append("<p>Deployment package does <b>not</b> resolve!<br/>");
+ }
+
+ sb.append("Details:<br/>");
+ sb.append(result.toString()).append("</p>");
+
+ return sb.toString();
+ }
+
+ /**
+ * Quietly closes a given {@link Closeable}.
+ *
+ * @param closeable the closeable to close, can be <code>null</code>.
+ */
+ private void closeQuietly(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ }
+ catch (IOException ex) {
+ // Ignore quietly...
+ }
+ }
+ }
+
+ /**
+ * Factory method to create a suitable {@link VerifyEnvironment} instance.
+ *
+ * @param manifest the manifest to use;
+ * @param verifyResult the verification result to use.
+ * @return a new {@link VerifyEnvironment} instance, never <code>null</code>.
+ */
+ @SuppressWarnings("deprecation")
+ private VerifyEnvironment createVerifyEnvironment(Map<String, String> manifest,
final VerificationResult verifyResult) {
+ String ee = manifest.get(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
+ if (ee == null) {
+ ee = VerifierService.EE_1_6;
+ }
+
+ Map<String, String> envMap = Collections.singletonMap(Constants.FRAMEWORK_EXECUTIONENVIRONMENT,
ee);
+
+ VerifyEnvironment env = m_verifier.createEnvironment(envMap, new VerifyReporter()
{
+ public void reportException(Exception ex) {
+ ex.printStackTrace(verifyResult.m_out);
+ }
+
+ public void reportLog(LogEntry logEntry) {
+ verifyResult.m_out.printf("Log (%l): [%s] %s", logEntry.getTime(), logEntry.getLevel(),
logEntry.getMessage());
+
+ Throwable ex = logEntry.getException();
+ if (ex != null) {
+ ex.printStackTrace(verifyResult.m_out);
+ }
+ }
+
+ public void reportWire(BundleRevision importer, BundleRequirement requirement,
BundleRevision exporter,
+ BundleCapability capability) {
+ verifyResult.m_out.println("<tt>WIRE: " + requirement + " -> " +
capability + "</tt><br/>");
+ }
+ });
+ return env;
+ }
+
+ /**
+ * Returns a "static"/hardcoded manifest.
+ *
+ * @return a manifest, never <code>null</code>.
+ */
+ private String defineStaticManifest() {
+ // @formatter:off
+ return Constants.BUNDLE_MANIFESTVERSION + ": 2\n" +
+ Constants.BUNDLE_SYMBOLICNAME + ": org.apache.felix.framework\n" +
+ Constants.EXPORT_PACKAGE + ": " + VerifierService.SYSTEM_PACKAGES + "," +
VerifierService.JRE_1_6_PACKAGES + "," +
+ "org.osgi.service.cm; version=1.2," +
+ "org.osgi.service.metatype; version=1.1.1," +
+ "org.osgi.service.cm; version=1.3.0," +
+ "org.osgi.service.deploymentadmin.spi; version=1.0.1," +
+ "org.osgi.service.deploymentadmin; version=1.1.0\n";
+ // @formatter:on
+ }
+
+ /**
+ * Returns the manifest for a given repository object.
+ * <p>In case the given repository object does not provide a manifest, this method
will return a hard-coded manifest.</p>
+ *
+ * @param object the repository object to get the manifest for, cannot be <code>null</code>.
+ * @return a manifest, never <code>null</code>.
+ */
+ private String getManifest(RepositoryObject object) {
+ String manifest = object.getAttribute("manifest");
+ if (manifest == null) {
+ manifest = defineStaticManifest();
+ }
+ return manifest;
+ }
+
+ /**
+ * Converts a given {@link Attributes} into a map.
+ *
+ * @param attributes the attributes to convert, cannot be <code>null</code>.
+ * @return a manifest map, never <code>null</code>.
+ */
+ private Map<String, String> getManifestEntries(final Manifest manifest) {
+ Attributes attributes = manifest.getMainAttributes();
+
+ Map<String, String> entries = new HashMap<String, String>();
+ for (Map.Entry<Object, Object> entry : attributes.entrySet()) {
+ entries.put(entry.getKey().toString(), entry.getValue().toString());
+ }
+ return entries;
+ }
+
+ /**
+ * @param manifestText
+ * @return
+ */
+ private Map<String, String> getManifestEntries(String manifestText) {
+ StringTokenizer tok = new StringTokenizer(manifestText, ":\n");
+
+ Map<String, String> manMap = new HashMap<String, String>();
+ while (tok.hasMoreTokens()) {
+ manMap.put(tok.nextToken(), tok.nextToken());
+ }
+ return manMap;
+ }
+
+ /**
+ * @param context
+ * @return
+ */
private RepositoryObject getRepositoryObjectFromContext(Map<String, Object> context)
{
Object contextObject = context.get("object");
if (contextObject == null) {
throw new IllegalStateException("No context object found");
}
- // It looks like there is some bug (or some other reason that escapes
- // me)
- // why ace is using either the object directly or wraps it in a
- // NamedObject first.
- // Its unclear when it does which so for now we cater for both.
- return ((RepositoryObject) (contextObject instanceof NamedObject ? ((NamedObject)
contextObject)
- .getObject() : contextObject));
- }
-
- class ManifestArea extends VerticalLayout implements Property.ValueChangeListener {
- private volatile String text;
- private final com.vaadin.ui.TextArea editor;
- private final String m_id;
- private TextArea plainText;
- private final RepositoryObject m_object;
- public ManifestArea(String id, String initialText, RepositoryObject object) {
- m_object = object;
- setCaption("VerifyResolve");
- m_id = id;
- setSpacing(true);
- setWidth("100%");
- text = initialText;
- editor = new com.vaadin.ui.TextArea(null, initialText);
- editor.setRows(18);
- editor.addListener(this);
- editor.setImmediate(true);
- editor.setWidth("100%");
- editor.setHeight("70%");
- addComponent(editor);
-
- Button verify = new Button("Verify");
- verify.addListener(new ClickListener() {
- private PopupView popup;
-
- public void buttonClick(ClickEvent event) {
- plainText.setReadOnly(false);
- try {
- DeploymentVersionObject version = m_repo.getMostRecentDeploymentVersion(m_id);
- if (version != null) {
- DeploymentArtifact[] artifacts = version.getDeploymentArtifacts();
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- final PrintStream out = new PrintStream(output);
- Set<BundleRevision> bundles = new HashSet<BundleRevision>();
- StringTokenizer tok = new StringTokenizer(editor.getValue().toString(),
":\n");
- Map<String, String> manMap = new HashMap<String, String>();
- while (tok.hasMoreTokens()) {
- manMap.put(tok.nextToken(), tok.nextToken());
- }
- String ee = manMap.get(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
- if (ee == null) {
- ee = VerifierService.EE_1_6;
- }
- final Map<String, String> envMap = new HashMap<String,
String>();
- envMap.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
- VerifyEnvironment env = m_verifier.createEnvironment(envMap,
new VerifyReporter() {
- public void reportWire(BundleRevision importer, BundleRequirement
reqirement, BundleRevision exporter, BundleCapability capability) {
- out.println("WIRE: " + reqirement + " -> " + capability
+ "\n");
- }
-
- public void reportLog(LogEntry logEntry) {
- out.println("Log(" + logEntry.getTime() + "): " + logEntry.getLevel()
+ " " + logEntry.getMessage());
- if (logEntry.getException() != null) {
- logEntry.getException().printStackTrace();
- }
- }
-
- public void reportException(Exception ex) {
- ex.printStackTrace(out);
- }
- });
- bundles.add(env.addBundle(0, manMap));
- Set<String> customizers = new HashSet<String>();
- Set<String> processors = new HashSet<String>();
- for (DeploymentArtifact data : artifacts) {
- if (data.getDirective(Constants.BUNDLE_SYMBOLICNAME) != null)
{
- JarInputStream input = null;
- try {
- input = new JarInputStream(new URL(data.getUrl()).openStream(),
false);
- final Attributes attributes = input.getManifest().getMainAttributes();
- Map<String, String> manifest = new HashMap<String,
String>();
- for (Map.Entry<Object, Object> entry : attributes.entrySet())
{
- manifest.put(entry.getKey().toString(), entry.getValue().toString());
- }
- bundles.add(env.addBundle(bundles.size(), manifest));
- if (attributes.getValue("DeploymentPackage-Customizer")
!= null) {
- String typeString = attributes.getValue("Deployment-ProvidesResourceProcessor");
- if (typeString != null) {
- String[] types = typeString.split(",");
- for (String type : types) {
- customizers.add(type.trim());
- }
- }
- }
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- finally {
- if (input != null) {
- try {
- input.close();
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
- }
- else {
- String processor = data.getDirective("Resource-Processor");
- if (processor != null) {
- processors.add(processor.trim());
- }
- }
- }
- plainText.setValue(("Customizers match: " + customizers.containsAll(processors)
+ "\n" + " (provided=" + customizers + ",required=" + processors + ")\n\n" + "Resolve: " +
env.verifyResolve(bundles, null, null) + "\n\n" + output.toString()));
- }
- }
- catch (Exception e) {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(output));
- plainText.setValue(output.toString());
- }
- if (popup != null) {
- removeComponent(popup);
+ return ((RepositoryObject) (contextObject instanceof NamedObject ? ((NamedObject)
contextObject).getObject()
+ : contextObject));
+ }
+
+ /**
+ * Processes all artifacts.
+ *
+ * @param artifacts the artifacts to process.
+ * @param env the environment to use;
+ * @param verifyResult the verification result, cannot be <code>null</code>.
+ */
+ private void processArtifacts(DeploymentArtifact[] artifacts, VerifyEnvironment env,
VerificationResult verifyResult) {
+ String dir;
+ for (DeploymentArtifact artifact : artifacts) {
+ if (artifact.getDirective(Constants.BUNDLE_SYMBOLICNAME) != null) {
+ processBundle(artifact, env, verifyResult);
+ }
+ else if ((dir = artifact.getDirective("Resource-Processor")) != null) {
+ verifyResult.addProcessor(dir);
+ }
+ }
+ }
+
+ /**
+ * Processes a single bundle.
+ *
+ * @param bundle the bundle to process;
+ * @param env the environment to use;
+ * @param verifyResult the verification result, cannot be <code>null</code>.
+ */
+ private void processBundle(DeploymentArtifact bundle, VerifyEnvironment env, VerificationResult
verifyResult) {
+ InputStream is = null;
+ JarInputStream jis = null;
+
+ try {
+ is = new URL(bundle.getUrl()).openStream();
+ jis = new JarInputStream(is, false /* verify */);
+
+ Map<String, String> manifest = getManifestEntries(jis.getManifest());
+
+ verifyResult.addBundle(env, manifest);
+
+ if (manifest.get("DeploymentPackage-Customizer") != null) {
+ String typeString = manifest.get("Deployment-ProvidesResourceProcessor");
+ if (typeString != null) {
+ String[] types = typeString.split(",");
+ for (String type : types) {
+ verifyResult.addCustomizer(type);
}
- plainText.setReadOnly(true);
- popup = new PopupView("Result", plainText);
- popup.setHideOnMouseOut(false);
- addComponent(popup);
- popup.setPopupVisible(true);
}
- });
- addComponent(verify);
- plainText = new TextArea();
- plainText.setImmediate(true);
- plainText.setWidth("600px");
- plainText.setHeight("400px");
- }
-
- public void valueChange(ValueChangeEvent event) {
- String text = (String) editor.getValue();
- if (text != null) {
- m_object.addAttribute("manifest", text);
}
}
+ catch (Exception ex) {
+ ex.printStackTrace(verifyResult.m_out);
+ }
+ finally {
+ closeQuietly(is);
+ closeQuietly(jis);
+ }
}
}
Added: ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java?rev=1311629&view=auto
==============================================================================
--- ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java
(added)
+++ ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java
Tue Apr 10 08:30:24 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.deployment.verifier.ui;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ace.deployment.verifier.VerifierService.VerifyEnvironment;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.wiring.BundleRevision;
+
+/**
+ * Provides the results of a verification.
+ */
+final class VerificationResult {
+ private final Set<String> m_customizers = new HashSet<String>();
+ private final Set<String> m_processors = new HashSet<String>();
+ private final Set<BundleRevision> m_bundles = new HashSet<BundleRevision>();
+ private final ByteArrayOutputStream m_output = new ByteArrayOutputStream();
+
+ final PrintStream m_out = new PrintStream(m_output);
+
+ public void addBundle(VerifyEnvironment env, Map<String, String> manifest) throws
BundleException {
+ m_bundles.add(env.addBundle(m_bundles.size(), manifest));
+ }
+
+ public void addCustomizer(String customizer) {
+ m_customizers.add(customizer.trim());
+ }
+
+ public void addProcessor(String processor) {
+ m_processors.add(processor.trim());
+ }
+
+ public boolean allCustomizerMatch() {
+ return m_customizers.containsAll(m_processors);
+ }
+
+ /**
+ * @return the bundles
+ */
+ public Set<BundleRevision> getBundles() {
+ return m_bundles;
+ }
+
+ /**
+ * @return the customizers
+ */
+ public Set<String> getCustomizers() {
+ return m_customizers;
+ }
+
+ /**
+ * @return the processors
+ */
+ public Set<String> getProcessors() {
+ return m_processors;
+ }
+
+ public boolean hasCustomizers() {
+ return !m_customizers.isEmpty() || !m_processors.isEmpty();
+ }
+
+ @Override
+ public String toString() {
+ return m_output.toString();
+ }
+}
\ No newline at end of file
Propchange: ace/trunk/ace-deployment-verifier-ui/src/main/java/org/apache/ace/deployment/verifier/ui/VerificationResult.java
------------------------------------------------------------------------------
svn:eol-style = native
|