Java tutorial
/* * 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.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.net.URL; import java.net.URLConnection; import java.util.Collections; import java.util.HashMap; import java.util.Map; 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.repository.DeploymentVersionRepository; import org.apache.ace.client.repository.stateful.StatefulTargetObject; import org.apache.ace.connectionfactory.ConnectionFactory; import org.apache.ace.deployment.verifier.VerifierService; import org.apache.ace.deployment.verifier.VerifierService.VerifyEnvironment; import org.apache.ace.deployment.verifier.VerifierService.VerifyReporter; import org.apache.ace.webui.UIExtensionFactory; import org.osgi.framework.Constants; import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleRequirement; import org.osgi.framework.wiring.BundleRevision; import org.osgi.service.log.LogEntry; 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.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 { /** * */ 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); } } } // Injected by Dependency Manager private volatile VerifierService m_verifier; private volatile DeploymentVersionRepository m_repo; private volatile ConnectionFactory m_connectionFactory; /** * {@inheritDoc} */ public Component create(Map<String, Object> context) { StatefulTargetObject target = getRepositoryObjectFromContext(context); Component content = new Label("This target is not yet registered, so it can not verify anything."); if (target.isRegistered()) { content = new ManifestArea(target.getID(), getManifest(target), target); } VerticalLayout result = new VerticalLayout(); 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<>(); 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<>(); while (tok.hasMoreTokens()) { manMap.put(tok.nextToken(), tok.nextToken()); } return manMap; } /** * @param context * @return */ private StatefulTargetObject getRepositoryObjectFromContext(Map<String, Object> context) { Object contextObject = context.get("statefulTarget"); if (contextObject == null) { throw new IllegalStateException("No context object found"); } return (StatefulTargetObject) 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 = getBundleContents(bundle.getUrl()); 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); } } } } catch (Exception ex) { ex.printStackTrace(verifyResult.m_out); } finally { closeQuietly(is); closeQuietly(jis); } } /** * @param url * the remote URL to connect to, cannot be <code>null</code>. * @return an {@link InputStream} to the remote URL, never <code>null</code>. * @throws IOException * in case of I/O problems opening the remote connection. */ private InputStream getBundleContents(String url) throws IOException { URLConnection conn = m_connectionFactory.createConnection(new URL(url)); return conn.getInputStream(); } }