| /******************************************************************************* |
| * Copyright (c) 1997-2007 by ProSyst Software GmbH |
| * http://www.prosyst.com |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * ProSyst Software GmbH - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.ip.impl; |
| |
| import java.io.*; |
| import java.lang.reflect.*; |
| import java.net.*; |
| import java.util.*; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipInputStream; |
| import org.eclipse.equinox.internal.ip.ProvisioningInfoProvider; |
| import org.eclipse.equinox.internal.ip.ProvisioningStorage; |
| import org.eclipse.equinox.internal.util.timer.Timer; |
| import org.eclipse.equinox.internal.util.timer.TimerListener; |
| import org.osgi.framework.*; |
| import org.osgi.service.provisioning.ProvisioningService; |
| |
| /** |
| * Class implementing provisioning management based on OSGi RFC 27. On start |
| * this <I>BundleActivator</I> gets its manifest headers |
| * <I>ProvisioningAgent.providerS</I> and <I>ProvisioningAgent.STORAGE</I>. |
| * Using them it decides which <I>ProvisioningInfoProvider</I>-s and which |
| * <I>ProvisioningStorage</I> are packed in the bundle. It make instances them. |
| * To be succesfull instantiation they MUST have constructor without parameters. |
| * All packed in bundle providers that implement <I>BundleActivator</I>. Their |
| * methods <I>start(BundleContext)</I> are invoked after instantiation. (On |
| * stop their <I>stop(BundleContext)</I>-s are invoked). ProvisioningStorage is |
| * used for saving provisioning service data. If no such storage thatas are lost |
| * on restart of bundle. Any fail in provider/storage instantiation, providers |
| * casting to <I>BundleActivator</I> ends with exception in bundle start and |
| * bundle will not reach state ACTIVE. |
| * |
| * Also it starts DiscoveryAgent which is prosyst's feature. It is constructed |
| * using values of system properties: "equinox.multicast.host" as host and |
| * "equinox.multicast.port" as port. If one of these properties is null no |
| * instance of DiscoveryAgent is made. |
| * |
| * @author Avgustin Marinov |
| * @author Pavlin Dobrev |
| * @version 1.0 |
| */ |
| |
| public class ProvisioningAgent implements BundleActivator, ProvisioningService, ServiceListener, FrameworkListener, TimerListener { |
| |
| /** |
| * This manifest header determines the packed into the provisioning agent |
| * bundle storage (if such exists) that is to be setarted. |
| */ |
| public final static String STORAGE = "Prv-Storage"; |
| |
| /** |
| * This manifest header determines URL Handlers packed into the provisioning |
| * agent bundle that are to be started. |
| */ |
| public final static String URL_HANDLERS = "Url-Handlers"; |
| |
| /** This system property that determines multicast host for discoverer agent. */ |
| public final static String MULTICAST_HOST = "equinox.provisioning.multicast.host"; |
| |
| /** This system property taht determines multicast port for discoverer agent. */ |
| public final static String MULTICAST_PORT = "equinox.provisioning.multicast.port"; |
| |
| /** |
| * This system property determines if provisioning can use HTTP transport |
| * (assumed as unsecured) for provisioning data assignments. |
| */ |
| public final static String HTTP_ALLOWED = "equinox.provisioning.httpprv.allowed"; |
| |
| /** |
| * This system property determines if provisioning must waits until the |
| * framework is started. |
| */ |
| public final static String WAIT_FW_START = "equinox.provisioning.prv.fwstart"; |
| |
| /** |
| * This system property determines if provisioning should try to make |
| * provisioning on every start |
| */ |
| public final static String REPROVISIONING_ON_START = "equinox.provisioning.reprovision.onstart"; |
| |
| /** |
| * Close Zip after reading. |
| */ |
| public final static String CLOSE_ZIP = "equinox.provisioning.close.zip"; |
| |
| /** |
| * This system property determines if provisioning agent should print debug |
| * and error information on the console. |
| */ |
| public final static String DEBUG = "equinox.provisioning.debug"; |
| |
| /** |
| * This system property determines if provisioning agent should print debug |
| * and error information on the console. |
| */ |
| public final static String REMOTE_DEBUG = "equinox.provisioning.remote.debug"; |
| |
| /** BundleContext used for interactions with framework. */ |
| public static BundleContext bc; |
| |
| /** Provisioning data. */ |
| private ProvisioningData info; |
| /** Registration of ProvisioningService. */ |
| private ServiceRegistration sreg; |
| /** |
| * Configuration store used for data storing. It is null after start if no |
| * storage packed in bundle. |
| */ |
| private ProvisioningStorage storage; |
| |
| /** If HTTP protocol is allows for provisioning data assignments. */ |
| private boolean httpAllowed; |
| |
| /** |
| * If storage is inner packed but it is not inner provider, and is |
| * BundleActivator and its start method has been invoked, it must be |
| * stopped. |
| */ |
| private boolean destroyStorageOnStop = false; |
| |
| /** |
| * Contains providers packed in bundle. It can be null after start if no |
| * providers packed in bundle. |
| */ |
| private Vector providers; |
| |
| /** |
| * Contains URL handlers packed in bundle. It can be null after start if no |
| * providers packed in bundle. |
| */ |
| private Vector urlHandlers; |
| |
| /** |
| * DiscoveryAgent instantiated by this object on start(BundleContext). It is |
| * null after start id host or port arenot set in manifest. |
| */ |
| private Runnable da; |
| |
| /** If there is need to wait for start of framework. */ |
| private boolean wfs; |
| /** If the information is added and provistioning assignements are allowed. */ |
| private boolean active; |
| /** |
| * Flag if the start data is processed from frameworkEvent or from |
| * start(BundleContext) method. |
| */ |
| private boolean startProcessed; |
| /** If to do reprovisiong */ |
| private boolean reprovision; |
| /** |
| * If the service is already registered. Used to be avided duplicated |
| * registration on start. |
| */ |
| private boolean registered; |
| /** If to close zip after reading */ |
| private boolean closeZip; |
| |
| // =================================================================================// |
| private static final int PROVISIONING = 1; |
| |
| private static final String HAS_FAILED_PROVISIONG = "!@#$_hasFailedPrv"; |
| |
| private boolean reAfterPrvFailureDisabled; |
| private int a; |
| private int b; |
| private int changePeriod; |
| private int maxPeriod; |
| |
| private Timer timer; |
| private long nextProvisioningAfter; |
| private int times; |
| // =================================================================================// |
| |
| public final static int ERROR_UNKNOWN = 0; |
| public final static int ERROR_LOAD_STORE_DATA = 1; |
| public final static int ERROR_MALFORMED_URL = 2; |
| public final static int ERROR_IO_EXCEPTION = 3; |
| public final static int ERROR_CORRUPTED_ZIP = 4; |
| |
| /** |
| * Invoked by framework on bundle start. |
| * |
| * @param bc |
| * bundle context |
| * @exception java.lang.Exception |
| * mostly when manifest dont match to packed |
| * providers/storage or their implementation do not match |
| * expectations. |
| */ |
| public void start(BundleContext bc) throws Exception { |
| ProvisioningAgent.bc = bc; |
| active = false; |
| startProcessed = false; |
| wfs = true; |
| if (bc.getProperty(WAIT_FW_START) != null) |
| if (bc.getProperty(WAIT_FW_START).equals("false")) |
| wfs = false; |
| httpAllowed = true; |
| if (bc.getProperty(HTTP_ALLOWED) != null) |
| if (bc.getProperty(HTTP_ALLOWED).equals("false")) |
| httpAllowed = false; |
| reprovision = getBoolean(ProvisioningAgent.REPROVISIONING_ON_START); |
| closeZip = getBoolean(CLOSE_ZIP); |
| |
| // =================================================================================// |
| reAfterPrvFailureDisabled = getBoolean("equinox.provisioning.provisioning.reAfterPrvFailure.disabled"); |
| a = getInteger("equinox.provisioning.provisioning.reAfterPrvFailure.a", 60000); |
| b = getInteger("equinox.provisioning.provisioning.reAfterPrvFailure.b", 60000); |
| changePeriod = getInteger("equinox.provisioning.provisioning.reAfterPrvFailure.changePeriod", 300000); |
| maxPeriod = getInteger("equinox.provisioning.provisioning.reAfterPrvFailure.maxperiod", 3600000); |
| nextProvisioningAfter = a; |
| // =================================================================================// |
| Log.j9workAround = getBoolean("equinox.provisioning.j9.2.0.workaround"); |
| Log.debug = getBoolean(DEBUG); |
| Log.remoteDebug = getBoolean(REMOTE_DEBUG); |
| Log.sendTrace = getBoolean("equinox.provisioning.send.trace"); |
| Log.prvSrv = this; |
| |
| org.eclipse.equinox.internal.util.ref.Log log = new org.eclipse.equinox.internal.util.ref.Log(bc); |
| log.setDebug(true); // always log to LogService! |
| log.setPrintOnConsole(Log.debug); |
| Log.log = log; |
| |
| try { |
| start0(bc); |
| } catch (Exception exc) { |
| Log.log.close(); |
| Log.log = null; |
| throw exc; |
| } |
| } |
| |
| private void start0(BundleContext bc) throws Exception { |
| Log.debug("Starting provisioning agent ..."); |
| |
| Bundle thisBundle = bc.getBundle(); |
| |
| // Starts URL handlers packed into the provisioning bundle |
| String urlHandlersHeader = (String) thisBundle.getHeaders().get(URL_HANDLERS); |
| if (urlHandlersHeader != null) { |
| StringTokenizer strTok = new StringTokenizer(urlHandlersHeader, ", "); |
| urlHandlers = new Vector(strTok.countTokens()); |
| while (strTok.hasMoreTokens()) { |
| try { |
| BundleActivator handler = (BundleActivator) Class.forName(strTok.nextToken().trim()).newInstance(); |
| handler.start(bc); |
| urlHandlers.addElement(handler); |
| } catch (Exception e) { |
| Log.debug("Can't instantiate or start a handler!"); |
| throw e; |
| } |
| } |
| urlHandlersHeader = null; |
| } |
| |
| // Gets inner storage activator class name (if inner storage exists). |
| String storageName = (String) thisBundle.getHeaders().get(STORAGE); |
| if (storageName != null) { |
| storageName.trim(); |
| } |
| |
| // Registers configuration providers packed into the bundle |
| String providersHeader = (String) thisBundle.getHeaders().get(ProvisioningInfoProvider.PROVIDERS); |
| if (providersHeader != null) { |
| providers = new Vector(5); |
| StringTokenizer strTok = new StringTokenizer(providersHeader, ",; "); |
| while (strTok.hasMoreTokens()) { |
| String providerName = strTok.nextToken().trim(); |
| strTok.nextToken(); // Skips ranking |
| Object provider = Class.forName(providerName).newInstance(); |
| if (provider instanceof BundleActivator) { |
| ((BundleActivator) provider).start(bc); |
| } |
| if (providerName.equals(storageName)) { |
| storage = (ProvisioningStorage) provider; |
| destroyStorageOnStop = true; |
| } |
| providers.addElement(provider); |
| } |
| } |
| |
| if (storage == null && storageName != null && storageName.length() != 0) { |
| try { |
| storage = (ProvisioningStorage) Class.forName(storageName).newInstance(); |
| if (storage instanceof BundleActivator) { |
| ((BundleActivator) storage).start(bc); |
| destroyStorageOnStop = true; |
| } |
| } catch (Exception e) { |
| Log.debug("Can't instantiate or start storage \"" + storage + "\"!"); |
| throw e; |
| } |
| } |
| |
| info = new ProvisioningData(); |
| |
| if (storage == null) { |
| synchronized (this) { |
| bc.addServiceListener(this, "(|" + '(' + Constants.OBJECTCLASS + '=' + ProvisioningStorage.class.getName() + ")" + '(' + Constants.OBJECTCLASS + '=' + ProvisioningInfoProvider.class.getName() + ")" + '(' + Constants.OBJECTCLASS + '=' + Timer.class.getName() + ')' + ")"); |
| |
| storage = getStorage(); |
| } |
| } else { |
| bc.addServiceListener(this, "(|" + '(' + Constants.OBJECTCLASS + '=' + ProvisioningInfoProvider.class.getName() + ')' + '(' + Constants.OBJECTCLASS + '=' + Timer.class.getName() + ')' + ")"); |
| } |
| |
| synchronized (this) { |
| if (timer == null) { |
| ServiceReference sRef = bc.getServiceReference(Timer.class.getName()); |
| if (sRef != null) { |
| timer = (Timer) bc.getService(sRef); |
| } |
| } |
| } |
| |
| if (storage != null) { |
| Log.debug("Loads from " + storage + " storage."); |
| try { |
| Dictionary storedInfo = storage.getStoredInfo(); |
| if (storedInfo != null && storedInfo.size() != 0) { |
| info.add(storedInfo); |
| } |
| } catch (Exception e) { // NPE or storage specific exception can be |
| // thrown |
| Log.debug(e); |
| setError(ERROR_LOAD_STORE_DATA, e.toString()); |
| if (destroyStorageOnStop) { |
| Log.debug("Warning: the storage could be unavailable!"); |
| } else { |
| storage = null; |
| } |
| } |
| } |
| |
| if (getHasFailedPrv() && !reAfterPrvFailureDisabled) { |
| reprovision = true; |
| } |
| |
| boolean hasLoadedInfo = false; |
| |
| ServiceReference[] srefs = bc.getServiceReferences(ProvisioningInfoProvider.class.getName(), null); |
| if (srefs != null) { |
| sort(srefs); |
| for (int i = 0; i < srefs.length; i++) { |
| ProvisioningInfoProvider provider = ((ProvisioningInfoProvider) bc.getService(srefs[i])); |
| try { |
| synchronized (info) { |
| if (!info.providers.contains(provider)) { |
| Log.debug("Loads from " + provider + " provider."); |
| info.providers.addElement(provider); |
| Dictionary toAdd = provider.init(this); |
| if (toAdd != null && toAdd.size() != 0) { |
| String prvref = (String) toAdd.get(ProvisioningService.PROVISIONING_REFERENCE); |
| if (prvref != null && prvref.trim().length() != 0) { // reference |
| // is |
| // changed |
| // by |
| // loader |
| reprovision = true; |
| } |
| info.add(toAdd); |
| hasLoadedInfo = true; |
| } |
| } |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| } |
| |
| if (!isFrameworkStarted()) { |
| bc.addFrameworkListener(this); |
| } else { |
| wfs = false; |
| } |
| |
| if (hasLoadedInfo) { |
| store(); |
| } |
| active = true; |
| processStart(); |
| |
| // Join GW to a multicast host. |
| try { |
| String host = "225.0.0.0"; |
| if (bc.getProperty(MULTICAST_HOST) != null) |
| host = bc.getProperty(MULTICAST_HOST); |
| String port = Integer.toString(getInteger(MULTICAST_PORT, 7777)); |
| if (host.length() != 0 && port.length() != 0) { |
| Class dscAgentClass = Class.forName("org.eclipse.equinox.internal.ip.impl.dscagent.DiscoveryAgent"); |
| Constructor constr = dscAgentClass.getConstructor(new Class[] {String.class, int.class, BundleContext.class, ProvisioningAgent.class}); |
| new Thread(da = (Runnable) constr.newInstance(new Object[] {host, new Integer(Integer.parseInt(port)), bc, this}), "Discovery Agent").start(); |
| } // "info" is already initialized |
| } catch (Throwable t) { |
| Log.debug("Can't create discovery agent!"); |
| } |
| Log.debug("Provisioning agent started ..."); |
| } |
| |
| /** |
| * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) |
| */ |
| public void stop(BundleContext bc) throws Exception { |
| Log.debug("Stopping provisionig agent ..."); |
| |
| if (timer != null) { |
| try { |
| timer.removeListener(this, PROVISIONING); |
| } catch (Throwable _) { |
| } |
| timer = null; |
| } |
| |
| registered = false; |
| |
| try { |
| bc.removeServiceListener(this); |
| } catch (Exception _) { |
| } |
| |
| try { |
| bc.removeFrameworkListener(this); |
| } catch (Exception _) { |
| } |
| |
| if (sreg != null) { |
| try { |
| sreg.unregister(); |
| } catch (Exception _) { |
| } |
| sreg = null; |
| } // Unregisters ProvisioningService |
| |
| if (da != null) { |
| try { |
| Method close = da.getClass().getMethod("close", new Class[] {}); |
| close.invoke(da, new Object[0]); |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| da = null; |
| } // Closes DiscoveryAgent |
| |
| if (storage != null) { |
| if (destroyStorageOnStop) { |
| try { |
| if (storage instanceof BundleActivator) { |
| ((BundleActivator) storage).stop(bc); |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| destroyStorageOnStop = false; |
| } |
| storage = null; |
| } // Stores data |
| |
| if (providers != null) { |
| for (int i = providers.size(); i-- > 0;) { |
| try { |
| ((BundleActivator) providers.elementAt(i)).stop(bc); |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| providers = null; |
| } // Stops providers |
| |
| if (urlHandlers != null) { |
| for (int i = urlHandlers.size(); i-- > 0;) { |
| try { |
| ((BundleActivator) urlHandlers.elementAt(i)).stop(bc); |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| urlHandlers = null; |
| } // Stops providers |
| |
| info = null; |
| Log.debug("Provisioning agent stopped ..."); |
| Log.log.close(); |
| Log.log = null; |
| } |
| |
| public Dictionary getInformation() { |
| return info; |
| } |
| |
| public void setInformation(Dictionary info) { |
| boolean refChanged = info.get(ProvisioningService.PROVISIONING_REFERENCE) != null; |
| synchronized (this.info) { |
| Integer version = (Integer) this.info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| Integer newVersion = new Integer(version.intValue() + 1); |
| this.info.set(info); |
| incrementUC(newVersion); |
| } |
| modify(); |
| updated(refChanged); |
| } |
| |
| public void addInformation(Dictionary info) { |
| addInformation(info, null); |
| } |
| |
| private static final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| private static final byte[] buffer = new byte[1024]; |
| |
| private static byte[] readStream(InputStream is) throws IOException { |
| synchronized (buffer) { |
| baos.reset(); |
| int read; |
| while ((read = is.read(buffer, 0, buffer.length)) != -1) { |
| baos.write(buffer, 0, read); |
| } |
| return baos.toByteArray(); |
| } |
| } |
| |
| private Bundle installBundle(String name, InputStream is) { |
| Bundle bundle = null; |
| try { |
| bundle = getBundle(name); |
| if (bundle == null) { /* install the bundle */ |
| if (Log.debug) |
| Log.debug("Installing management bundle '" + name + "'"); |
| bundle = bc.installBundle(name, is); |
| } else { /* just update it */ |
| if (Log.debug) |
| Log.debug("Updating management bundle '" + name + "'"); |
| bundle.update(is); |
| } |
| } catch (Throwable t) { |
| setHasFailedPrv(true); |
| Log.debug("WARNING: Failed to install management bundle '" + name + "'", t); |
| } |
| return bundle; |
| } |
| |
| public void addInformation(ZipInputStream zis) { |
| Log.debug("Add Information form ZIS."); |
| Hashtable entries = new Hashtable(2);//cache for unprocessed entries |
| boolean manifestFound = false; |
| Dictionary info = new Hashtable(5); |
| Dictionary entriesFromHeader = null; |
| Dictionary extraFileds = null; |
| Vector bundlesToStart = new Vector(5); |
| String header = null; |
| try { |
| ZipEntry ze; |
| String name, type; |
| /* read the rest of the entries */ |
| while ((ze = zis.getNextEntry()) != null) { |
| /* read name */ |
| name = ze.getName(); |
| if (name.endsWith("/")) {// path entry |
| zis.closeEntry(); |
| continue; |
| |
| } |
| if (name.charAt(0) == '/') |
| name = name.substring(1); |
| /* read extra */ |
| byte[] extra = ze.getExtra(); |
| type = extra == null ? null : new String(extra).toLowerCase(); |
| if (extra != null && !"META-INF/MANIFEST.MF".equals(name)) { |
| if (extraFileds == null) { |
| extraFileds = new Hashtable(3, 3); |
| } |
| extraFileds.put(name, type); |
| }//the extra field is null or the entry is the manifest |
| if (!manifestFound) { |
| if ("META-INF/MANIFEST.MF".equals(name)) {//the entry is the manifest |
| manifestFound = true; |
| header = getHeaderFromManifest(zis); |
| entriesFromHeader = filterAttributes(TYPE, parseEntries(header)); |
| } else {//no manifest yet, so cache the entry |
| System.out.println("---put : " + name); |
| entries.put(name, readStream(zis)); |
| } |
| } else {//the manifest is found so we process the entry |
| processEntry(extraFileds, name, null, zis, info, entriesFromHeader, bundlesToStart); |
| } |
| zis.closeEntry(); |
| } |
| |
| /*process the cached entries*/ |
| Enumeration names = entries.keys(); |
| while (names.hasMoreElements()) { |
| processEntry(extraFileds, name = (String) names.nextElement(), (byte[]) entries.get(name), null, info, entriesFromHeader, bundlesToStart); |
| } |
| } catch (Throwable e) { |
| this.info.setError(ERROR_CORRUPTED_ZIP, e.toString()); |
| Log.debug("Error reading provisioning package", e); |
| setHasFailedPrv(true); |
| } |
| |
| /* close the zip file */ |
| if (closeZip) { |
| try { |
| zis.close(); |
| } catch (Exception _) { |
| } |
| } |
| |
| /* update info and start all required bundles */ |
| addInformation(info, bundlesToStart); // bundle should |
| } |
| |
| private void processEntry(Dictionary extraFileds, String name, byte[] content, InputStream is, Dictionary info, Dictionary entriesFromHeader, Vector bundlesToStart) throws IOException { |
| /* |
| * first try the InitialProvisioning-Entries header |
| * if the zip file had a manifest entry |
| */ |
| String type = entriesFromHeader == null ? null : (String) entriesFromHeader.get(name); |
| /* |
| * If there is no value in the InitialProvisioning-Entries header for that path |
| * try to initialize the type from the entry's extra field. |
| * If this ZIP entry field is present, the Initial Provisioning service should not |
| * look further, even if the extra field contains an erroneous value. |
| */ |
| if (type == null) { |
| if (extraFileds != null) { |
| type = (String) extraFileds.get(name); |
| } |
| } |
| /* |
| * if type is still null try to to initialize it |
| * according to the extension of the entry's name |
| */ |
| if (type == null) { |
| type = getMIMEfromExtension(name); |
| } |
| |
| /* process entry */ |
| if (Log.debug) { |
| Log.debug("Processing entry '" + name + "' of type " + type); |
| } |
| if (MIME_BUNDLE.equals(type) || MIME_BUNDLE_ALT.equals(type)) { |
| installBundle(name, content == null ? new ISWrapper(is) : new ISWrapper(new ByteArrayInputStream(content))); |
| } else if (MIME_BYTE_ARRAY.equals(type)) { |
| info.put(name, content == null ? readStream(is) : content); |
| } else if (MIME_STRING.equals(type)) { |
| String value = getUTF8String(content == null ? readStream(is) : content); |
| info.put(name, value); |
| /* |
| * FIXME: actually there can be only ONE key of that type! - so why |
| * using vector |
| */ |
| if (PROVISIONING_START_BUNDLE.equals(name)) { |
| /* Make management agent bundle deployment. Sets java.security.AllPermission |
| * if PermissionAdmin is available..*/ |
| try { |
| grantAllPermissions(value); |
| } catch (Throwable e) { |
| Log.debug("Failed to grant all permissions", e); |
| } |
| bundlesToStart.addElement(value); |
| } |
| } else if (MIME_BUNDLE_URL.equals(type)) { |
| String value = getUTF8String(content == null ? readStream(is) : content); |
| installBundle(name, new URL(value).openStream()); |
| } else { |
| this.info.setError(ERROR_CORRUPTED_ZIP, // |
| "Unknown MIME type (" + type + ") for entry '" + name + "'"); |
| setHasFailedPrv(true); |
| } |
| } |
| |
| public void serviceChanged(ServiceEvent se) { |
| Object service = bc.getService(se.getServiceReference()); |
| if (service instanceof ProvisioningStorage) { |
| if (se.getType() == ServiceEvent.REGISTERED) { |
| synchronized (this) { |
| if (storage == null) { // If there is a storage it won't be |
| // replaced. |
| storage = (ProvisioningStorage) service; |
| } else { |
| return; |
| } |
| } |
| try { |
| Object oldUC = info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| int iOldUC = 0; |
| if (oldUC != null && oldUC instanceof Integer) { |
| iOldUC = ((Integer) oldUC).intValue(); |
| } |
| |
| Dictionary toAdd = storage.getStoredInfo(); |
| Object newUC = toAdd.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| int iNewUC = 0; |
| if (newUC != null && newUC instanceof Integer) { |
| iNewUC = ((Integer) newUC).intValue(); |
| } |
| |
| boolean refChanged = toAdd.get(ProvisioningService.PROVISIONING_REFERENCE) != null && (iNewUC == 0 || reprovision); |
| |
| boolean increment = iNewUC > iOldUC; // In this case it |
| // is assummed that |
| // is most probably |
| // that this |
| // is the original version but storage is started after the |
| // provisioning bundle. |
| |
| synchronized (info) { |
| info.set(toAdd); |
| if (increment) { |
| incrementUC(new Integer(iNewUC)); |
| modify(); |
| } |
| } |
| |
| updated(refChanged); |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| Log.debug("Storage is available."); |
| } else if (se.getType() == ServiceEvent.UNREGISTERING) { |
| if (storage == bc.getService(se.getServiceReference())) { |
| Log.debug("Storage is removed!"); |
| try { |
| storage.store(info); |
| } catch (Exception e) { |
| Log.debug("Can't store provisioning info!", e); |
| } |
| storage = null; // No more than one Storage service should |
| // be registered on the FW |
| } |
| } |
| } |
| |
| if (service instanceof ProvisioningInfoProvider) { // a Storage could |
| // be a Provider |
| if (se.getType() == ServiceEvent.REGISTERED) { |
| ProvisioningInfoProvider provider = (ProvisioningInfoProvider) service; |
| Log.debug("Loads from " + provider + " provider."); |
| try { |
| if (!info.providers.contains(provider)) { |
| Dictionary toAdd = provider.init(this); |
| boolean refChanged = false; |
| if (toAdd != null) { |
| String prvref = (String) toAdd.get(ProvisioningService.PROVISIONING_REFERENCE); |
| if (prvref != null && prvref.trim().length() != 0) { // reference |
| // is |
| // changed |
| // by |
| // loader |
| refChanged = true; |
| } |
| } |
| boolean added = true; |
| synchronized (info) { |
| if (!info.providers.contains(provider)) { |
| info.providers.addElement(provider); |
| info.add(toAdd); |
| if (refChanged) { |
| reprovision = true; |
| } |
| Integer version = (Integer) info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| Integer newVersion = new Integer(version.intValue() + 1); |
| incrementUC(newVersion); |
| } else { |
| added = false; |
| } |
| } |
| if (added) { |
| modify(); |
| updated(refChanged); |
| } |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } else if (se.getType() == ServiceEvent.UNREGISTERING) { |
| info.providers.removeElement(service); |
| } |
| } |
| |
| if (service instanceof Timer) { // timer is expected to be single |
| // service |
| switch (se.getType()) { |
| case ServiceEvent.REGISTERED : { |
| synchronized (this) { |
| if (timer == null) { |
| timer = (Timer) service; |
| if (getHasFailedPrv() && !reAfterPrvFailureDisabled) { |
| try { |
| timer.notifyAfterMillis(this, nextPrvAfter(), PROVISIONING); // TO DO - Won't be |
| // updated with newer |
| // method - it will not |
| // run on older FW |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| } |
| } |
| break; |
| } |
| case ServiceEvent.UNREGISTERING : { |
| timer = null; |
| break; |
| } |
| } |
| } |
| } |
| |
| public synchronized void timer(int event) { |
| Log.debug("Timer event " + event); |
| try { |
| switch (event) { |
| case PROVISIONING : { |
| Log.debug("Remake failed provisioning."); |
| if (getHasFailedPrv()) { |
| processPrvAssignment(); |
| } |
| break; |
| } |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| |
| public void frameworkEvent(FrameworkEvent event) { |
| if (event.getType() == FrameworkEvent.STARTED) { |
| wfs = false; |
| processStart(); |
| } |
| } |
| |
| public boolean getHttpAllowed() { |
| return httpAllowed; |
| } |
| |
| // Synchronize frameworkEvent and start(BundleContext) initial reactions |
| private void processStart() { |
| synchronized (this) { |
| try { |
| Log.debug("Reprovision = " + reprovision + ", update counter = " + info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT) + ", provisioning reference = " + info.get(ProvisioningService.PROVISIONING_REFERENCE)); |
| if ((reprovision || ((Integer) info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT)).intValue() == 0) && info.get(ProvisioningService.PROVISIONING_REFERENCE) != null) { |
| if (!startProcessed) { |
| if (processPrvAssignment()) { |
| startProcessed = true; |
| } |
| } |
| } |
| } catch (Throwable t) { |
| Log.debug(t); |
| } |
| } |
| |
| synchronized (this) { |
| if (active && !wfs && !registered) { |
| registered = true; |
| } else { |
| return; |
| } |
| } |
| Log.debug("Registering ProvisioningService."); |
| sreg = bc.registerService(ProvisioningService.class.getName(), this, getRegProps()); |
| } |
| |
| /** |
| * This is called by ProvisioningData when one puts new |
| * <I>ProvisioningService.PROVISIONING_UPDATE_COUNT</I>. |
| * |
| * @param refChanged |
| * if ProvisioningService.PROVISIONING_REFERENCE changed |
| */ |
| private void updated(boolean refUpdated) { |
| Log.debug("ProvisioingDictionary updated. Reference updated = " + refUpdated); |
| |
| store(); |
| |
| synchronized (this) { |
| if (refUpdated) { |
| if (!processPrvAssignment()) { |
| reprovision = true; |
| } |
| } |
| } |
| } |
| |
| private void store() { |
| if (storage != null) { |
| try { |
| Dictionary info = this.info; |
| if (info != null) { |
| storage.store(info); |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } else { |
| Log.debug("Warning: No storage available."); |
| } |
| } |
| |
| private boolean processPrvAssignment() { |
| if (active && !wfs) { |
| new Thread() { |
| public void run() { |
| try { |
| process(); |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| }.start(); |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Make provisioning data assignement to nextRef. |
| * |
| * @param nextRef |
| * next reference. |
| */ |
| synchronized void process() { |
| if (info == null) |
| return; // the bundle is stopped |
| setHasFailedPrv(false); |
| String ref = (String) info.get(ProvisioningService.PROVISIONING_REFERENCE); |
| Log.debug("Reference = \"" + ref + '"'); |
| if (ref != null && (ref = ref.trim()).length() != 0) { |
| String spid = (String) info.get(ProvisioningService.PROVISIONING_SPID); |
| Log.debug("Setup from \"" + ref + "\", SPID = " + spid); |
| |
| if (!httpAllowed) { |
| if (ref.startsWith("http://")) { |
| Log.debug("Won't make setup to " + ref + " because http is forbidden!"); |
| setError(ERROR_MALFORMED_URL, "Provisioning reference is a HTTP URL, but non-secure HTTP is forbidden!"); |
| setHasFailedPrv(true); |
| return; |
| } |
| } |
| |
| if (!ref.startsWith("file:") && ref.indexOf("service_platform_id") == -1) { |
| if (ref.indexOf('?') == -1) { |
| ref += '?'; |
| } else { |
| ref += '&'; |
| } |
| ref += "service_platform_id" + '=' + URLEncoder.encode(spid == null ? "" : spid); |
| } |
| Log.debug("Setup url = \"" + ref); |
| |
| URLConnection conn = null; |
| |
| try { |
| URL url = new URL(ref); |
| InputStream is = null; |
| |
| try { |
| conn = url.openConnection(); |
| if (conn == null) { |
| throw new IOException("Can't open connection to " + url + "!"); |
| } |
| conn.setRequestProperty("Connection", "close"); |
| |
| conn.connect(); |
| String error = conn.getHeaderField("error"); // Such |
| // error |
| // message |
| // is not by |
| // specification |
| // and is |
| // returned |
| // by |
| // Provisioining |
| // Service |
| // Backend |
| if (error == null) { |
| if ((conn instanceof HttpURLConnection) && ((HttpURLConnection) conn).getResponseCode() != HttpURLConnection.HTTP_OK) { |
| String errorMsg = "Warning! ResponseCode = " + ((HttpURLConnection) conn).getResponseCode() + "!"; |
| Log.debug(errorMsg); |
| setError(ERROR_IO_EXCEPTION, errorMsg); |
| } else { |
| is = conn.getInputStream(); |
| } |
| } else { |
| setError(ERROR_IO_EXCEPTION, error); |
| Log.debug("Error from Backend: " + error + "! Setup failed!"); |
| } |
| } catch (IOException e) { |
| setError(ERROR_IO_EXCEPTION, e.toString()); |
| Log.debug(e); |
| } |
| |
| if (is == null) { |
| setHasFailedPrv(true); |
| } else { |
| try { |
| ZipInputStream zis = new ZipInputStream(is); |
| try { |
| addInformation(zis); // the addInformation method |
| // closes stream |
| Log.debug("Setup ended."); |
| } finally { |
| if (!closeZip) { |
| try { |
| zis.close(); |
| } catch (Exception _) { |
| } |
| } |
| } |
| } catch (Exception e) { |
| setError(ERROR_CORRUPTED_ZIP, e.toString()); |
| setHasFailedPrv(true); |
| Log.debug(e); |
| } |
| } |
| } catch (IOException e) { // new URL ---> MalformedURLException |
| setError(ERROR_MALFORMED_URL, "Invalid Provisioning Reference: " + ref); |
| } finally { |
| if (conn != null && conn instanceof HttpURLConnection) { |
| try { |
| ((HttpURLConnection) conn).disconnect(); |
| } catch (Exception _) { |
| } |
| } |
| } |
| } |
| |
| if (getHasFailedPrv()) { |
| if (!reAfterPrvFailureDisabled) { |
| try { |
| if (timer != null) { |
| timer.notifyAfterMillis(this, nextPrvAfter(), PROVISIONING); // TO DO - Won't be updated with |
| // newer method - it will not |
| // run on older FW |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| } else { |
| times = 0; |
| nextProvisioningAfter = a; |
| } |
| } |
| |
| private synchronized long nextPrvAfter() { |
| times++; |
| if (nextProvisioningAfter < maxPeriod && nextProvisioningAfter * times > changePeriod) { |
| nextProvisioningAfter += b; |
| times = 0; |
| } |
| Log.debug("Next bootstrap after " + nextProvisioningAfter + "ms"); |
| return nextProvisioningAfter; |
| } |
| |
| // bundlesToStart is null on addInfo from provider/storage, and != null on |
| // add from ZIS |
| // pending error must be cleared only in second case! |
| private void addInformation(Dictionary info, Vector bundlesToStart) { |
| boolean refChanged = info.get(ProvisioningService.PROVISIONING_REFERENCE) != null; |
| synchronized (this.info) { |
| this.info.add(info); |
| Integer version = (Integer) this.info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| Integer newVersion = new Integer(version.intValue() + 1); |
| incrementUC(newVersion); |
| } |
| |
| Log.debug("Bundles to start: " + bundlesToStart); |
| if (bundlesToStart != null) { |
| for (int i = 0; i < bundlesToStart.size(); i++) { |
| Object next = bundlesToStart.elementAt(i); |
| try { |
| if (next instanceof Bundle) { |
| ((Bundle) next).start(); |
| } else { |
| Bundle b = getBundle((String) next); |
| if (b != null) { |
| b.start(); |
| } else { |
| Log.debug("Can't find '" + next + "' bundle to start it!"); |
| } |
| } |
| } catch (Exception e) { |
| Log.debug("Exception while starting " + (next instanceof Bundle ? ((Bundle) next).getLocation() : next), e); |
| setHasFailedPrv(true); |
| return; |
| } |
| } |
| |
| clearError(); |
| } |
| |
| modify(); |
| updated(refChanged); |
| } |
| |
| private boolean isFrameworkStarted() { |
| if (!wfs) |
| return true; |
| Bundle system = bc.getBundle(0); |
| return system != null ? system.getState() == Bundle.ACTIVE : true; |
| } |
| |
| /** |
| * Make management agent bundle deployment. Sets java.security.AllPermission |
| * if PermissionAdmin is available.. |
| * |
| * @param maRef |
| * management agent reference. |
| */ |
| private void grantAllPermissions(String location) { |
| try { |
| ServiceReference sref = bc.getServiceReference("org.osgi.service.permissionadmin.PermissionAdmin"); // the |
| // org.osgi.service.permissionadmin is not imported for R1 |
| if (sref != null) { |
| Method method = Class.forName("org.osgi.service.permissionadmin.PermissionAdmin").getMethod("setPermissions", new Class[] {String.class, Class.forName("[Lorg.osgi.service.permissionadmin.PermissionInfo;")}); |
| Object[] allPerms = (Object[]) Array.newInstance(Class.forName("org.osgi.service.permissionadmin.PermissionInfo"), 1); |
| Constructor constr = Class.forName("org.osgi.service.permissionadmin.PermissionInfo").getConstructor(new Class[] {String.class, String.class, String.class}); |
| allPerms[0] = constr.newInstance(new String[] {"java.security.AllPermission", "", ""}); |
| method.invoke(bc.getService(sref), new Object[] {location, allPerms}); |
| } |
| } catch (Exception e) { |
| Log.debug(e); |
| } |
| } |
| |
| private ProvisioningStorage getStorage() { |
| ServiceReference sref = bc.getServiceReference(ProvisioningStorage.class.getName()); |
| return sref != null ? (ProvisioningStorage) bc.getService(sref) : null; |
| } |
| |
| private Bundle getBundle(String location) { |
| Bundle[] bundles = bc.getBundles(); |
| for (int i = bundles.length; i-- > 0;) { |
| if (location.equalsIgnoreCase(bundles[i].getLocation())) { |
| return bundles[i]; |
| } |
| } |
| return null; |
| } |
| |
| private void incrementUC(Integer uc) { |
| if (!active) { |
| return; |
| } |
| info.putUC(uc); |
| } |
| |
| private void modify() { |
| if (!active || sreg == null) { |
| return; |
| } |
| try { |
| sreg.setProperties(getRegProps()); |
| } catch (Exception e) { |
| } |
| } |
| |
| private Dictionary getRegProps() { |
| Hashtable prvsprops = new Hashtable(1, 1.0F); |
| prvsprops.put("Vendor", "ProSyst"); |
| prvsprops.put(ProvisioningService.PROVISIONING_UPDATE_COUNT, info.get(ProvisioningService.PROVISIONING_UPDATE_COUNT)); |
| return prvsprops; |
| } |
| |
| private void sort(ServiceReference[] srefs) { |
| for (int i = srefs.length - 1; i > 0; i--) { |
| for (int j = 0; j < i; j++) { |
| if (less(srefs[j + 1], srefs[j])) { |
| ServiceReference temp = srefs[j]; |
| srefs[j] = srefs[j + 1]; |
| srefs[j + 1] = temp; |
| } |
| } |
| } |
| } |
| |
| private boolean less(ServiceReference sref1, ServiceReference sref2) { |
| return getRanking(sref1) < getRanking(sref2); |
| } |
| |
| private int getRanking(ServiceReference sref) { |
| Integer ranking = (Integer) sref.getProperty(Constants.SERVICE_RANKING); |
| return ranking == null ? 0 : ranking.intValue(); |
| } |
| |
| private String getUTF8String(byte[] body) { |
| try { |
| return new String(body, "UTF-8"); |
| } catch (Exception _0) { |
| try { |
| return new String(body, "UTF8"); // for personal java |
| // problems |
| } catch (Exception _1) { |
| return new String(body); |
| } |
| } |
| } |
| |
| private void setError(int code, String message) { |
| ProvisioningData data = this.info; |
| if (data == null) { |
| return; |
| } |
| |
| data.setError(code, message); |
| |
| Integer version = (Integer) data.get(ProvisioningService.PROVISIONING_UPDATE_COUNT); |
| Integer newVersion = new Integer(version.intValue() + 1); |
| info.putUC(newVersion); |
| |
| modify(); |
| } |
| |
| private void clearError() { |
| ProvisioningData data = this.info; |
| if (data == null) { |
| return; |
| } |
| |
| data.clearError(); |
| } |
| |
| private boolean getHasFailedPrv() { |
| return "true".equals(info.get(HAS_FAILED_PROVISIONG)); |
| } |
| |
| private void setHasFailedPrv(boolean hasFailedPrv) { |
| if (getHasFailedPrv() != hasFailedPrv) { |
| info.putPrivate(HAS_FAILED_PROVISIONG, hasFailedPrv ? "true" : null); |
| store(); |
| } |
| } |
| |
| /** |
| * Parses the InitialProvisioning-Entries manifest header. |
| * @param header the contents of the InitialProvisioning-Entries manifest header, if any |
| * @return Dictionary which maps entry paths to Dictionary representing the attributes |
| * or null, if no header is found. |
| */ |
| private static Dictionary parseEntries(String header) { |
| Dictionary entries = null; |
| Dictionary attributes = null; |
| header = removeWhiteSpaces(header); |
| if (header == null || header.length() == 0) |
| return null; |
| int begin = 0, end = 1, length = header.length(); |
| boolean quoted = false; |
| String path, attribute, value; |
| |
| entry: while (end != -1 && begin < length - 1) { |
| end = readToken(header, begin, false, false); //read the path |
| if (end == -1) |
| break; //end of header, or only path |
| |
| switch (header.charAt(end)) { |
| case ';' ://end of path , read attribute |
| if (begin == end) { |
| end = readToken(header, end + 1, false, true); |
| begin = end + 1; |
| continue; |
| } |
| path = header.substring(begin, end); |
| begin = end + 1; |
| //read the attributes |
| while (end != -1 && begin < length - 1) { |
| end = readToken(header, begin, quoted, false); |
| if (end == -1) |
| break entry; |
| if (header.charAt(end) != '=' || begin == end) { |
| //invalid syntax |
| end = readToken(header, begin, false, true); //read the attribute name |
| begin = end + 1; |
| continue entry; |
| } |
| attribute = header.substring(begin, end); |
| if (header.charAt(begin) == '\"') { |
| quoted = true; |
| begin = end + 2; |
| } else |
| begin = end + 1; |
| |
| if (begin >= length - 1) |
| break entry; |
| |
| end = readToken(header, begin, quoted, false); //read the attribute value |
| if (end == -1) { |
| if (quoted) { |
| //invalid syntax |
| end = readToken(header, begin, false, true); |
| begin = end + 1; |
| continue entry; |
| } |
| //end of header or last attribute-value |
| value = header.substring(begin, length); |
| if (attributes == null) |
| attributes = new Hashtable(2, 3); |
| attributes.put(attribute, value); |
| begin = end + 1; |
| break; |
| } |
| switch (header.charAt(end)) { |
| case ',' : //end of parameters list |
| value = header.substring(begin, end); |
| if (attributes == null) |
| attributes = new Hashtable(2, 3); |
| attributes.put(attribute, value); |
| if (entries == null) |
| entries = new Hashtable(3, 3); |
| entries.put(path, attributes); |
| attributes = null; |
| continue entry; |
| case ';' : //another parameter |
| value = header.substring(begin, end); |
| if (attributes == null) |
| attributes = new Hashtable(2, 3); |
| attributes.put(attribute, value); |
| begin = end + 1; |
| continue; |
| case '\"' : //endof quoted part |
| quoted = false; |
| value = header.substring(begin, end - 1); |
| if (attributes == null) |
| attributes = new Hashtable(2, 3); |
| attributes.put(attribute, value); |
| begin = end + 1; |
| continue; |
| default : //invalid syntax |
| end = readToken(header, begin, false, true); |
| begin = end + 1; |
| continue entry; |
| } |
| } |
| break; |
| case ',' : //no description |
| if (begin == end) |
| begin = end + 2; |
| else |
| begin = end + 1; |
| continue; |
| default :// invalid syntax |
| end = readToken(header, end + 1, false, true); |
| begin = end + 1; |
| continue; |
| } |
| |
| if (attributes != null) { |
| if (entries == null) |
| entries = new Hashtable(3, 3); |
| entries.put(path, attributes); |
| attributes = null; |
| } |
| } |
| return entries; |
| } |
| |
| /** |
| * Reads the next token from the manifest header. |
| * @param token the valiue of the manifest header. |
| * @param begin index of the char from which to start |
| * @param quoted if the consequent part of teh string is guoted |
| * @param skipInvalidPath if true all chars till the first comma are skipped |
| * @return the index of the first character from the string which is |
| * different from the expected, or -1 if not found |
| */ |
| private static int readToken(String token, int begin, boolean quoted, boolean skipInvalidPath) { |
| char c = 0; |
| int len = token.length(); |
| if (begin >= len) |
| return -1; |
| if (quoted) { |
| while ((c = token.charAt(begin)) != '\"') { |
| if (++begin == len) |
| return -1; |
| } |
| return begin; |
| } |
| if (skipInvalidPath) { |
| while ((c = token.charAt(begin)) != ',') { |
| if (++begin == len) |
| return -1; |
| } |
| return begin; |
| } |
| while ((c = token.charAt(begin)) >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_' || c == '-' || c == '/' || c == '.' || c == ':') { |
| if (++begin == len) |
| return -1; |
| } |
| return begin; |
| } |
| |
| static final String TYPE = "type"; |
| |
| /** |
| * Filters the Dictionary returned from {@link #parseEntries(String)}. |
| * Returns Dictionary which maps entry paths to values of the attribute, |
| * which name is given as argument. |
| */ |
| private static Dictionary filterAttributes(String attribute, Dictionary entries) { |
| if (entries == null) |
| return null; |
| Dictionary filtered = null; |
| Enumeration paths = entries.keys(); |
| Dictionary attributes = null; |
| String path = null, type = null, mime = null; |
| while (paths.hasMoreElements()) { |
| path = (String) paths.nextElement(); |
| attributes = (Dictionary) entries.get(path); |
| if ((type = (String) attributes.get(attribute)) != null && (mime = typeToMIME(type)) != null) { |
| if (filtered == null) |
| filtered = new Hashtable(3, 3); |
| filtered.put(path, mime); |
| } |
| } |
| return filtered; |
| } |
| |
| /** |
| * Maps type to an appropriate mime type constant |
| * @param type the value of the type attribute from the InitialProvisioning-Entries header |
| * @return the mime type for the string type or null if type is not a valid type |
| */ |
| private static String typeToMIME(String type) { |
| if ("text".equals(type)) |
| return ProvisioningService.MIME_STRING; |
| if ("binary".equals(type)) |
| return ProvisioningService.MIME_BYTE_ARRAY; |
| if ("bundle".equals(type)) |
| return ProvisioningService.MIME_BUNDLE; |
| if ("bundle-url".equals(type)) |
| return ProvisioningService.MIME_BUNDLE_URL; |
| return null; |
| } |
| |
| /** |
| * @param filename the name of the zip entry |
| * @return the MIME type of the entry according to its extension |
| * or null if the mime type cannot be defined |
| */ |
| static String getMIMEfromExtension(String filename) { |
| int index = filename.lastIndexOf("."); |
| //no extension -> we cannot identify the type |
| if (index == -1) |
| return null; |
| String extension = filename.substring(index + 1); |
| if (extension.equals("jar")) |
| return ProvisioningService.MIME_BUNDLE; |
| if (extension.equals("txt")) |
| return ProvisioningService.MIME_STRING; |
| if (extension.equals("url")) |
| return ProvisioningService.MIME_BUNDLE_URL; |
| return ProvisioningService.MIME_BYTE_ARRAY; |
| } |
| |
| /** |
| * @param is the InputStream containing the information in the manifest |
| * @return the contents of the InitialProvisioning-Entries header if any or null otherwise |
| */ |
| private static String getHeaderFromManifest(InputStream is) { |
| boolean blank = false; |
| StringBuffer header = new StringBuffer(); |
| BufferedReader br = new BufferedReader(new InputStreamReader(is)); |
| String line = null; |
| boolean loop = true; |
| try { |
| while ((line = br.readLine()) != null && loop) { |
| if (line.length() == 0) { |
| if (blank) { |
| break; |
| } |
| blank = true; |
| continue; |
| } else { |
| blank = false; |
| } |
| if (line.startsWith(ProvisioningService.INITIALPROVISIONING_ENTRIES)) { |
| header.append(removeWhiteSpaces(line.substring(ProvisioningService.INITIALPROVISIONING_ENTRIES.length() + 1))); |
| line = br.readLine();//next line |
| while (loop = (line.length() != 0 && Character.isWhitespace(line.charAt(0)))) { |
| header.append(removeWhiteSpaces(line)); |
| line = br.readLine(); |
| } |
| } |
| } |
| } catch (IOException ioe) { |
| return null; |
| } |
| return (header.length() == 0 ? null : header.toString()); |
| } |
| |
| private static String removeWhiteSpaces(String s) { |
| if (s == null) |
| return null; |
| char curr; |
| StringBuffer sb = new StringBuffer(); |
| for (int i = 0; i < s.length(); i++) { |
| if (!Character.isWhitespace(curr = s.charAt(i))) { |
| sb.append(curr); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| private static class ISWrapper extends InputStream { |
| |
| private InputStream is; |
| |
| ISWrapper(InputStream is) { |
| this.is = is; |
| } |
| |
| public int read() throws IOException { |
| return is.read(); |
| } |
| |
| public int read(byte[] src, int off, int len) throws IOException { |
| return is.read(src, off, len); |
| } |
| |
| public void close() { |
| } |
| } |
| |
| public static boolean getBoolean(String property) { |
| String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property); |
| return ((prop != null) && prop.equalsIgnoreCase("true")); |
| } |
| |
| public static int getInteger(String property, int defaultValue) { |
| String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property); |
| if (prop != null) { |
| try { |
| return Integer.decode(prop).intValue(); |
| } catch (NumberFormatException e) { |
| //do nothing |
| } |
| } |
| return defaultValue; |
| } |
| } |