1 /******************************************************************************* 2 * Copyright (c) 2013, 2017 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.osgi.tests.hooks.framework.storage.a; 15 16 import java.io.ByteArrayInputStream; 17 import java.io.ByteArrayOutputStream; 18 import java.io.DataInputStream; 19 import java.io.DataOutputStream; 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.net.URLConnection; 23 import java.util.Collections; 24 import java.util.Dictionary; 25 import java.util.HashMap; 26 import java.util.Map; 27 import java.util.concurrent.atomic.AtomicInteger; 28 import java.util.jar.Attributes; 29 import java.util.jar.JarOutputStream; 30 import java.util.jar.Manifest; 31 import org.eclipse.osgi.container.Module; 32 import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent; 33 import org.eclipse.osgi.container.ModuleRevisionBuilder; 34 import org.eclipse.osgi.container.ModuleRevisionBuilder.GenericInfo; 35 import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory; 36 import org.eclipse.osgi.internal.hookregistry.HookConfigurator; 37 import org.eclipse.osgi.internal.hookregistry.HookRegistry; 38 import org.eclipse.osgi.internal.hookregistry.StorageHookFactory; 39 import org.eclipse.osgi.storage.BundleInfo.Generation; 40 import org.osgi.framework.BundleActivator; 41 import org.osgi.framework.BundleContext; 42 import org.osgi.framework.Constants; 43 import org.osgi.framework.Version; 44 import org.osgi.framework.namespace.BundleNamespace; 45 import org.osgi.framework.namespace.IdentityNamespace; 46 47 public class TestHookConfigurator implements HookConfigurator { 48 private static class TestStorageHookFactory extends StorageHookFactory<Object, Object, TestStorageHookFactory.TestStorageHook> { 49 private static class TestStorageHook extends StorageHookFactory.StorageHook<Object, Object> { 50 private static AtomicInteger adaptCount = new AtomicInteger(1); 51 TestStorageHook(Generation generation, Class clazz)52 public TestStorageHook(Generation generation, Class clazz) { 53 super(generation, clazz); 54 } 55 56 @Override initialize(Dictionary manifest)57 public void initialize(Dictionary manifest) { 58 // Nothing 59 } 60 61 @Override load(Object loadContext, DataInputStream is)62 public void load(Object loadContext, DataInputStream is) { 63 if (TestHookConfigurator.failLoad) { 64 // will force a clean 65 throw new IllegalArgumentException(); 66 } 67 } 68 69 @Override save(Object saveContext, DataOutputStream os)70 public void save(Object saveContext, DataOutputStream os) { 71 // Nothing. 72 } 73 74 @Override validate()75 public void validate() throws IllegalStateException { 76 TestHookConfigurator.validateCalled = true; 77 if (TestHookConfigurator.invalid) 78 throw new IllegalStateException(); 79 } 80 81 @Override deletingGeneration()82 public void deletingGeneration() { 83 TestHookConfigurator.deletingGenerationCalled = true; 84 } 85 86 @Override adaptModuleRevisionBuilder(ModuleEvent operation, Module origin, ModuleRevisionBuilder builder)87 public ModuleRevisionBuilder adaptModuleRevisionBuilder(ModuleEvent operation, Module origin, ModuleRevisionBuilder builder) { 88 if (TestHookConfigurator.replaceModuleBuilder) { 89 ModuleRevisionBuilder replace = new ModuleRevisionBuilder(); 90 // try setting the ID to something which is checked during the test 91 replace.setId(5678); 92 replace.setSymbolicName("replace"); 93 replace.setVersion(Version.parseVersion("1.1.1")); 94 replace.addCapability("replace", Collections.<String, String> emptyMap(), Collections.<String, Object> emptyMap()); 95 replace.addCapability(IdentityNamespace.IDENTITY_NAMESPACE, Collections.<String, String> emptyMap(), Collections.<String, Object> singletonMap(IdentityNamespace.IDENTITY_NAMESPACE, "replace")); 96 replace.addCapability(BundleNamespace.BUNDLE_NAMESPACE, Collections.<String, String> emptyMap(), Collections.<String, Object> singletonMap(BundleNamespace.BUNDLE_NAMESPACE, "replace")); 97 return replace; 98 } 99 if (TestHookConfigurator.adaptManifest) { 100 // try setting the ID to something which is checked during the test 101 builder.setId(5678); 102 Map<String, String> dirs = Collections.emptyMap(); 103 Map<String, Object> attrs = new HashMap<>(); 104 attrs.put("test.file.path", getGeneration().getContent().getPath() + " - " + adaptCount.getAndIncrement()); 105 attrs.put("test.operation", operation.toString()); 106 attrs.put("test.origin", origin.getLocation()); 107 builder.addCapability("test.file.path", dirs, attrs); 108 } 109 if (TestHookConfigurator.adaptCapabilityAttribute) { 110 for (GenericInfo c : builder.getCapabilities()) { 111 if (BundleNamespace.BUNDLE_NAMESPACE.equals(c.getNamespace())) { 112 c.getAttributes().put("matching.attribute", "testAttribute"); 113 c.getDirectives().put("matching.directive", "testDirective"); 114 } 115 } 116 } 117 return builder; 118 } 119 } 120 TestStorageHookFactory()121 public TestStorageHookFactory() { 122 } 123 124 @Override getStorageVersion()125 public int getStorageVersion() { 126 return 0; 127 } 128 129 @Override createStorageHook(Generation generation)130 protected TestStorageHook createStorageHook(Generation generation) { 131 createStorageHookCalled = true; 132 if (returnNullStorageHook) { 133 return null; 134 } 135 Class<?> factoryClass = TestStorageHookFactory.class; 136 if (invalidFactoryClass) 137 factoryClass = StorageHookFactory.class; 138 return new TestStorageHook(generation, factoryClass); 139 } 140 141 @Override handleContentConnection(Module module, String location, InputStream in)142 public URLConnection handleContentConnection(Module module, String location, InputStream in) throws IOException { 143 if (handleContentConnection) { 144 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 145 Manifest manifest = new Manifest(); 146 Attributes attrs = manifest.getMainAttributes(); 147 attrs.putValue("Manifest-Version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$ 148 attrs.putValue(Constants.BUNDLE_MANIFESTVERSION, "2"); 149 attrs.putValue(Constants.BUNDLE_SYMBOLICNAME, "testHandleContentConnection"); 150 JarOutputStream jos = new JarOutputStream(baos, manifest); 151 jos.close(); 152 return new URLConnection(null) { 153 @Override 154 public void connect() { 155 connected = true; 156 } 157 158 @Override 159 public InputStream getInputStream() { 160 return new ByteArrayInputStream(baos.toByteArray()); 161 } 162 }; 163 } 164 return super.handleContentConnection(module, location, in); 165 } 166 } 167 168 public static volatile boolean createStorageHookCalled; 169 public static volatile boolean invalid; 170 public static volatile boolean failLoad; 171 public static volatile boolean invalidFactoryClass; 172 public static volatile boolean validateCalled; 173 public static volatile boolean deletingGenerationCalled; 174 public static volatile boolean adaptManifest; 175 public static volatile boolean adaptCapabilityAttribute; 176 public static volatile boolean replaceModuleBuilder; 177 public static volatile boolean handleContentConnection; 178 public static volatile boolean returnNullStorageHook; 179 180 public void addHooks(HookRegistry hookRegistry) { 181 hookRegistry.addStorageHookFactory(new TestStorageHookFactory()); 182 hookRegistry.addActivatorHookFactory(new ActivatorHookFactory() { 183 184 @Override 185 public BundleActivator createActivator() { 186 return new BundleActivator() { 187 188 @Override 189 public void start(BundleContext context) throws Exception { 190 TestHelper.testBundle = context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION); 191 } 192 193 @Override 194 public void stop(BundleContext context) throws Exception { 195 // nothing 196 } 197 }; 198 } 199 }); 200 } 201 } 202