You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ma...@apache.org on 2008/01/30 17:46:39 UTC
svn commit: r616813 [3/9] - in /felix/trunk/deploymentadmin: ./ src/
src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/felix/
src/main/java/org/apache/felix/deploymentadmin/
src/main/java/org/apache/felix/de...
Added: felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/StopBundleCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/StopBundleCommand.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/StopBundleCommand.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/StopBundleCommand.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,76 @@
+/*
+ * 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.felix.deploymentadmin.spi;
+
+import org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.service.deploymentadmin.BundleInfo;
+import org.osgi.service.deploymentadmin.DeploymentException;
+import org.osgi.service.log.LogService;
+
+/**
+ * Command that stops all bundles described in the target deployment package of a deployment session.
+ */
+public class StopBundleCommand extends Command {
+
+ public void execute(DeploymentSessionImpl session) throws DeploymentException {
+ AbstractDeploymentPackage target = session.getTargetAbstractDeploymentPackage();
+ BundleInfo[] bundleInfos = target.getOrderedBundleInfos();
+ for (int i = 0; i < bundleInfos.length; i++) {
+ if (isCancelled()) {
+ throw new DeploymentException(DeploymentException.CODE_CANCELLED);
+ }
+ Bundle bundle = target.getBundle(bundleInfos[i].getSymbolicName());
+ if (bundle != null) {
+ addRollback(new StartBundleRunnable(bundle));
+ try {
+ bundle.stop();
+ }
+ catch (BundleException e) {
+ session.getLog().log(LogService.LOG_WARNING, "Could not stop bundle '" + bundle.getSymbolicName() + "'", e);
+ }
+ }
+ else {
+ session.getLog().log(LogService.LOG_WARNING, "Could not stop bundle '" + bundleInfos[i].getSymbolicName() + "' because it was not defined int he framework");
+ }
+ }
+ }
+
+ private class StartBundleRunnable implements Runnable {
+
+ private final Bundle m_bundle;
+
+ public StartBundleRunnable(Bundle bundle) {
+ m_bundle = bundle;
+ }
+
+ public void run() {
+ try {
+ m_bundle.start();
+ }
+ catch (BundleException e) {
+ // TODO: log this
+ e.printStackTrace();
+ }
+ }
+
+ }
+}
+
Added: felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,168 @@
+/*
+ * 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.felix.deploymentadmin.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
+import org.apache.felix.deploymentadmin.AbstractInfo;
+import org.apache.felix.deploymentadmin.BundleInfoImpl;
+import org.apache.felix.deploymentadmin.Constants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentException;
+
+/**
+ * Command that installs all bundles described in the source deployment package of a deployment
+ * session. If a bundle was already defined in the target deployment package of the same session
+ * it is updated, otherwise the bundle is simply installed.
+ */
+public class UpdateCommand extends Command {
+
+ public void execute(DeploymentSessionImpl session) throws DeploymentException {
+ AbstractDeploymentPackage source = session.getSourceAbstractDeploymentPackage();
+ AbstractDeploymentPackage targetPackage = session.getTargetAbstractDeploymentPackage();
+ BundleContext context = session.getBundleContext();
+
+ Map expectedBundles = new HashMap();
+ AbstractInfo[] bundleInfos = (AbstractInfo[]) source.getBundleInfos();
+ for (int i = 0; i < bundleInfos.length; i++) {
+ AbstractInfo bundleInfo = bundleInfos[i];
+ if(!bundleInfo.isMissing()) {
+ expectedBundles.put(bundleInfo.getPath(), bundleInfo);
+ }
+ }
+
+ try {
+ for (AbstractInfo entry = source.getNextEntry(); (entry != null) && (!expectedBundles.isEmpty()); entry = source.getNextEntry()) {
+ String name = entry.getPath();
+ if (!expectedBundles.containsKey(name)) {
+ throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Resource '" + name + "' is not described in the manifest.");
+ }
+
+ BundleInfoImpl bundleInfo = (BundleInfoImpl) expectedBundles.remove(name);
+ Bundle bundle = source.getBundle(bundleInfo.getSymbolicName());
+ try {
+ if (bundle == null) {
+ // new bundle, install it
+ bundle = context.installBundle(Constants.BUNDLE_LOCATION_PREFIX + bundleInfo.getSymbolicName(), new BundleInputStream(source.getCurrentEntryStream()));
+ addRollback(new UninstallBundleRunnable(bundle));
+ } else {
+ // existing bundle, update it
+ Version sourceVersion = bundleInfo.getVersion();
+ Version targetVersion = Version.parseVersion((String) bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION));
+ if (!sourceVersion.equals(targetVersion)) {
+ bundle.update(new BundleInputStream(source.getCurrentEntryStream()));
+ addRollback(new UpdateBundleRunnable(bundle, targetPackage, bundleInfo.getSymbolicName()));
+ }
+ }
+ }
+ catch (BundleException be) {
+ if (isCancelled()) {
+ return;
+ }
+ throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not install new bundle '" + name + "'", be);
+ }
+ if (!bundle.getSymbolicName().equals(bundleInfo.getSymbolicName()) || !Version.parseVersion((String)bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION)).equals(bundleInfo.getVersion())) {
+ throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Installed/updated bundle version and/or symbolicnames do not match what was installed/updated");
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Problem while reading stream", e);
+ }
+ }
+
+ private static class UninstallBundleRunnable implements Runnable {
+
+ private final Bundle m_bundle;
+
+ public UninstallBundleRunnable(Bundle bundle) {
+ m_bundle = bundle;
+ }
+
+ public void run() {
+ try {
+ m_bundle.uninstall();
+ }
+ catch (BundleException e) {
+ // TODO: log this
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static class UpdateBundleRunnable implements Runnable {
+
+ private final Bundle m_bundle;
+ private final AbstractDeploymentPackage m_targetPackage;
+ private final String m_symbolicName;
+
+ public UpdateBundleRunnable(Bundle bundle, AbstractDeploymentPackage targetPackage, String symbolicName) {
+ m_bundle = bundle;
+ m_targetPackage = targetPackage;
+ m_symbolicName = symbolicName;
+ }
+
+ public void run() {
+ try {
+ m_bundle.update(m_targetPackage.getBundleStream(m_symbolicName));
+ }
+ catch (Exception e) {
+ // TODO: log this
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private final class BundleInputStream extends InputStream {
+ private final InputStream m_inputStream;
+
+ private BundleInputStream(InputStream jarInputStream) {
+ m_inputStream = jarInputStream;
+ }
+
+ public int read() throws IOException {
+ checkCancel();
+ return m_inputStream.read();
+ }
+
+ public int read(byte[] buffer) throws IOException {
+ checkCancel();
+ return m_inputStream.read(buffer);
+ }
+
+ public int read(byte[] buffer, int off, int len) throws IOException {
+ checkCancel();
+ return m_inputStream.read(buffer, off, len);
+ }
+
+ private void checkCancel() throws IOException {
+ if (isCancelled()) {
+ throw new IOException("Stream was cancelled");
+ }
+ }
+ }
+
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationContext.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationContext.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationContext.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,355 @@
+/*
+ * $Header: /cvshome/build/org.osgi.application/src/org/osgi/application/ApplicationContext.java,v 1.15 2006/07/11 13:19:02 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.application;
+
+import java.util.Dictionary;
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+
+
+/**
+ * <code>ApplicationContext</code> is the access point for an OSGi-aware
+ * application to the features of the OSGi Service Platform. Each application
+ * instance will have its own <code>ApplicationContext</code> instance, which
+ * will not be reused after destorying the corresponding application instace.
+ * <p>
+ * Application instances can obtain their <code>ApplicationContext</code>
+ * using the {@link Framework#getApplicationContext} method.
+ * <p>
+ * The lifecycle of an <code>ApplicationContext</code> instance is bound to
+ * the lifecycle of the corresponding application instance. The
+ * <code>ApplicationContext</code> becomes available when the application is
+ * started and it is invalidated when the application instance is stopped (i.e.
+ * the "stop" method of the application activator object returned).
+ * All method calls (except {@link #getApplicationId()} and
+ * {@link #getInstanceId()}) to an invalidated context object result an
+ * <code>IllegalStateException</code>.
+ *
+ * @see org.osgi.application.Framework
+ */
+public interface ApplicationContext {
+
+ /**
+ * Adds the specified {@link ApplicationServiceListener} object to this context
+ * application instance's list of listeners. The specified <code>referenceName</code> is a
+ * reference name specified in the descriptor of the corresponding application. The registered
+ * <code>listener> will only receive the {@link ApplicationServiceEvent}s realted to the referred service.
+ * <p>
+ * If the <code>listener</code> was already added, calling this method will overwrite the previous
+ * registration.
+ * <p>
+ *
+ * @param listener
+ * The {@link org.osgi.application.ApplicationServiceListener} to be added. It must
+ * not be <code>null</code>
+ * @param referenceName the reference name of a service from the descriptor of the corresponding
+ * application. It must not be <code>null</code>.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ * @throws java.lang.NullPointerException If <code>listener</code> or <code>referenceName</code>
+ * is <code>null</code>
+ * @throws java.lang.IllegalArgumentException If there is no service in the
+ * application descriptor with the specified <code>referenceName</code>.
+ */
+ public void addServiceListener(ApplicationServiceListener listener, String referenceName) throws java.lang.IllegalArgumentException;
+
+ /**
+ * Adds the specified {@link ApplicationServiceListener} object to this context
+ * application instance's list of listeners. The <code>referenceNames</code> parameter is an
+ * array of reference name specified in the descriptor of the corresponding application. The registered
+ * <code>listener> will only receive the {@link ApplicationServiceEvent}s realted to the referred
+ * services.
+ * <p>
+ * If the <code>listener</code> was already added, calling this method will overwrite the previous
+ * registration.
+ * <p>
+ *
+ * @param listener
+ * The {@link org.osgi.application.ApplicationServiceListener} to be added. It must not
+ * be <code>null</code>
+ * @param referenceNames and array of service reference names from the descriptor of the corresponding
+ * application. It must not be <code>null</code> and it must not be empty.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ * @throws java.lang.NullPointerException If <code>listener</code> or <code>referenceNames</code>
+ * is <code>null</code>
+ * @throws java.lang.IllegalArgumentException If <code>referenceNames</code> array is empty or it
+ * contains unknown references
+ */
+ public void addServiceListener(ApplicationServiceListener listener, String[] referenceNames) throws java.lang.IllegalArgumentException;
+
+ /**
+ * Removes the specified {@link org.osgi.application.ApplicationServiceListener} object from this
+ * context application instances's list of listeners.
+ * <p>
+ * If <code>listener</code> is not contained in this context application
+ * instance's list of listeners, this method does nothing.
+ *
+ * @param listener
+ * The {@link org.osgi.application.ApplicationServiceListener} object to be removed.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ */
+ public void removeServiceListener(ApplicationServiceListener listener);
+
+ /**
+ * This method returns the identifier of the corresponding application instace.
+ * This identifier is guarateed to be unique within the scope of the device.
+ *
+ * Note: this method can safely be called on an invalid
+ * <code>ApplicationContext</code> as well.
+ *
+ * @see org.osgi.service.application.ApplicationHandle#getInstanceId()
+ *
+ * @return the unique identifier of the corresponding application instance
+ */
+ public String getInstanceId();
+
+ /**
+ * This method return the identifier of the correspondig application type. This identifier
+ * is the same for the different instances of the same application but it is different for
+ * different application type.
+ * <p>
+ * Note: this method can safely be called on an invalid
+ * <code>ApplicationContext</code> as well.
+ *
+ * @see org.osgi.service.application.ApplicationDescriptor#getApplicationId()
+ *
+ * @return the identifier of the application type.
+ */
+ public String getApplicationId();
+
+ /**
+ * This method returns the service object for the specified
+ * <code>referenceName</code>. If the cardinality of the reference is
+ * 0..n or 1..n and multiple services are bound to the reference, the
+ * service with the highest ranking (as specified in its
+ * {@link org.osgi.framework.Constants#SERVICE_RANKING} property) is returned. If there
+ * is a tie in ranking, the service with the lowest service ID (as specified
+ * in its {@link org.osgi.framework.Constants#SERVICE_ID} property); that is, the
+ * service that was registered first is returned.
+ *
+ * @param referenceName
+ * The name of a reference as specified in a reference element in
+ * this context applications's description. It must not be <code>null</code>
+ * @return A service object for the referenced service or <code>null</code>
+ * if the reference cardinality is 0..1 or 0..n and no bound service
+ * is available.
+ * @throws java.lang.NullPointerException If <code>referenceName</code> is <code>null</code>.
+ * @throws java.lang.IllegalArgumentException If there is no service in the
+ * application descriptor with the specified <code>referenceName</code>.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ */
+ public Object locateService(String referenceName);
+
+ /**
+ * This method returns the service objects for the specified
+ * <code>referenceName</code>.
+ *
+ * @param referenceName
+ * The name of a reference as specified in a reference element in
+ * this context applications's description. It must not be
+ * <code>null</code>.
+ * @return An array of service object for the referenced service or
+ * <code>null</code> if the reference cardinality is 0..1 or 0..n
+ * and no bound service is available.
+ * @throws java.lang.NullPointerException If <code>referenceName</code> is <code>null</code>.
+ * @throws java.lang.IllegalArgumentException If there is no service in the
+ * application descriptor with the specified <code>referenceName</code>.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ */
+ public Object[] locateServices(String referenceName);
+
+ /**
+ * Returns the startup parameters specified when calling the
+ * {@link org.osgi.service.application.ApplicationDescriptor#launch}
+ * method.
+ * <p>
+ * Startup arguments can be specified as name, value pairs. The name
+ * must be of type {@link java.lang.String}, which must not be
+ * <code>null</code> or empty {@link java.lang.String} (<code>""</code>),
+ * the value can be any object including <code>null</code>.
+ *
+ * @return a {@link java.util.Map} containing the startup arguments.
+ * It can be <code>null</code>.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ */
+ public Map getStartupParameters();
+
+ /**
+ * Application can query the service properties of a service object
+ * it is bound to. Application gets bound to a service object when
+ * it fisrt obtains a reference to the service by calling
+ * <code>locateService</code> or <code>locateServices</code> methods.
+ *
+ * @param serviceObject A service object the application is bound to.
+ * It must not be null.
+ * @return The service properties associated with the specified service
+ * object.
+ * @throws NullPointerException if the specified <code>serviceObject</code>
+ * is <code>null</code>
+ * @throws IllegalArgumentException if the application is not
+ * bound to the specified service object or it is not a service
+ * object at all.
+ * @throws java.lang.IllegalStateException
+ * If this context application instance has stopped.
+ */
+ public Map getServiceProperties(Object serviceObject);
+
+
+ /**
+ * Registers the specified service object with the specified properties
+ * under the specified class names into the Framework. A
+ * {@link org.osgi.framework.ServiceRegistration} object is returned. The
+ * {@link org.osgi.framework.ServiceRegistration} object is for the private use of the
+ * application registering the service and should not be shared with other
+ * applications. The registering application is defined to be the context application.
+ * Bundles can locate the service by using either the
+ * {@link org.osgi.framework.BundleContext#getServiceReferences} or
+ * {@link org.osgi.framework.BundleContext#getServiceReference} method. Other applications
+ * can locate this service by using {@link #locateService(String)} or {@link #locateServices(String)}
+ * method, if they declared their dependece on the registered service.
+ *
+ * <p>
+ * An application can register a service object that implements the
+ * {@link org.osgi.framework.ServiceFactory} interface to have more flexibility in providing
+ * service objects to other applications or bundles.
+ *
+ * <p>
+ * The following steps are required to register a service:
+ * <ol>
+ * <li>If <code>service</code> is not a <code>ServiceFactory</code>,
+ * an <code>IllegalArgumentException</code> is thrown if
+ * <code>service</code> is not an <code>instanceof</code> all the
+ * classes named.
+ * <li>The Framework adds these service properties to the specified
+ * <code>Dictionary</code> (which may be <code>null</code>): a property
+ * named {@link org.osgi.framework.Constants#SERVICE_ID} identifying the registration number of
+ * the service and a property named {@link org.osgi.framework.Constants#OBJECTCLASS} containing
+ * all the specified classes. If any of these properties have already been
+ * specified by the registering bundle, their values will be overwritten by
+ * the Framework.
+ * <li>The service is added to the Framework service registry and may now
+ * be used by others.
+ * <li>A service event of type {@link org.osgi.framework.ServiceEvent#REGISTERED} is
+ * fired. This event triggers the corresponding {@link ApplicationServiceEvent} to be
+ * delivered to the applications that registered the appropriate listener.
+ * <li>A <code>ServiceRegistration</code> object for this registration is
+ * returned.
+ * </ol>
+ *
+ * @param clazzes The class names under which the service can be located.
+ * The class names in this array will be stored in the service's
+ * properties under the key {@link org.osgi.framework.Constants#OBJECTCLASS}.
+ * This parameter must not be <code>null</code>.
+ * @param service The service object or a <code>ServiceFactory</code>
+ * object.
+ * @param properties The properties for this service. The keys in the
+ * properties object must all be <code>String</code> objects. See
+ * {@link org.osgi.framework.Constants} for a list of standard service property keys.
+ * Changes should not be made to this object after calling this
+ * method. To update the service's properties the
+ * {@link org.osgi.framework.ServiceRegistration#setProperties} method must be called.
+ * The set of properties may be <code>null</code> if the service
+ * has no properties.
+ *
+ * @return A {@link org.osgi.framework.ServiceRegistration} object for use by the application
+ * registering the service to update the service's properties or to
+ * unregister the service.
+ *
+ * @throws java.lang.IllegalArgumentException If one of the following is
+ * true:
+ * <ul>
+ * <li><code>service</code> is <code>null</code>.
+ * <li><code>service</code> is not a <code>ServiceFactory</code>
+ * object and is not an instance of all the named classes in
+ * <code>clazzes</code>.
+ * <li><code>properties</code> contains case variants of the same
+ * key name.
+ * </ul>
+ * @throws NullPointerException if <code>clazzes</code> is <code>null</code>
+ *
+ * @throws java.lang.SecurityException If the caller does not have the
+ * <code>ServicePermission</code> to register the service for all
+ * the named classes and the Java Runtime Environment supports
+ * permissions.
+ *
+ * @throws java.lang.IllegalStateException If this ApplicationContext is no
+ * longer valid.
+ *
+ * @see org.osgi.framework.BundleContext#registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
+ * @see org.osgi.framework.ServiceRegistration
+ * @see org.osgi.framework.ServiceFactory
+ */
+ public ServiceRegistration registerService(String[] clazzes,
+ Object service, Dictionary properties);
+
+ /**
+ * Registers the specified service object with the specified properties
+ * under the specified class name with the Framework.
+ *
+ * <p>
+ * This method is otherwise identical to
+ * {@link #registerService(java.lang.String[], java.lang.Object,
+ * java.util.Dictionary)} and is provided as a convenience when
+ * <code>service</code> will only be registered under a single class name.
+ * Note that even in this case the value of the service's
+ * {@link Constants#OBJECTCLASS} property will be an array of strings,
+ * rather than just a single string.
+ *
+ * @param clazz The class name under which the service can be located. It
+ * must not be <code>null</code>
+ * @param service The service object or a <code>ServiceFactory</code>
+ * object.
+ * @param properties The properties for this service.
+ *
+ * @return A <code>ServiceRegistration</code> object for use by the application
+ * registering the service to update the service's properties or to
+ * unregister the service.
+ *
+ * @throws java.lang.IllegalArgumentException If one of the following is
+ * true:
+ * <ul>
+ * <li><code>service</code> is <code>null</code>.
+ * <li><code>service</code> is not a <code>ServiceFactory</code>
+ * object and is not an instance of the named class in
+ * <code>clazz</code>.
+ * <li><code>properties</code> contains case variants of the same
+ * key name.
+ * </ul>
+ * @throws NullPointerException if <code>clazz</code> is <code>null</code>
+ *
+ * @throws java.lang.SecurityException If the caller does not have the
+ * <code>ServicePermission</code> to register the service
+ * the named class and the Java Runtime Environment supports
+ * permissions.
+ *
+ * @throws java.lang.IllegalStateException If this ApplicationContext is no
+ * longer valid.
+ * @see #registerService(java.lang.String[], java.lang.Object,
+ * java.util.Dictionary)
+ */
+ public ServiceRegistration registerService(String clazz, Object service,
+ Dictionary properties);
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceEvent.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceEvent.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceEvent.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceEvent.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,83 @@
+/*
+ * $Header: /cvshome/build/org.osgi.application/src/org/osgi/application/ApplicationServiceEvent.java,v 1.6 2006/07/11 13:19:02 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.application;
+
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * An event from the Framework describing a service lifecycle change.
+ * <p>
+ * <code>ApplicationServiceEvent</code> objects are delivered to a
+ * <code>ApplicationServiceListener</code> objects when a change occurs in this service's
+ * lifecycle. The delivery of an <code>ApplicationServiceEvent</code> is
+ * always triggered by a {@link org.osgi.framework.ServiceEvent}.
+ * <code>ApplicationServiceEvent</code> extends the content of <code>ServiceEvent</code>
+ * with the service object the event is referring to as applications has no means to
+ * find the corresponding service object for a {@link org.osgi.framework.ServiceReference}.
+ * A type code is used to identify the event type for future
+ * extendability. The available type codes are defined in {@link org.osgi.framework.ServiceEvent}.
+ *
+ * <p>
+ * OSGi Alliance reserves the right to extend the set of types.
+ *
+ * @see org.osgi.framework.ServiceEvent
+ * @see ApplicationServiceListener
+ *
+ * @version $Revision: 1.6 $
+ */
+public class ApplicationServiceEvent extends ServiceEvent {
+
+ private static final long serialVersionUID = -4762149286971897323L;
+ final Object serviceObject;
+
+ /**
+ * Creates a new application service event object.
+ *
+ * @param type The event type. Available type codes are defines in
+ * {@link org.osgi.framework.ServiceEvent}
+ * @param reference A <code>ServiceReference</code> object to the service
+ * that had a lifecycle change. This reference will be used as the <code>source</code>
+ * in the {@link java.util.EventObject} baseclass, therefore, it must not be
+ * null.
+ * @param serviceObject The service object bound to this application instance. It can
+ * be <code>null</code> if this application is not bound to this service yet.
+ * @throws IllegalArgumentException if the specified <code>reference</code> is null.
+ */
+ public ApplicationServiceEvent(int type, ServiceReference reference, Object serviceObject) {
+ super(type, reference);
+ this.serviceObject = serviceObject;
+ }
+
+ /**
+ * This method returns the service object of this service bound to the listener
+ * application instace. A service object becomes bound to the application when it
+ * first obtains a service object reference to that service by calling the
+ * <code>ApplicationContext.locateService</code> or <code>locateServices</code>
+ * methods. If the application is not bound to the service yet, this method returns
+ * <code>null</code>.
+ *
+ * @return the service object bound to the listener application or <code>null</code>
+ * if it isn't bound to this service yet.
+ */
+ public Object getServiceObject() {
+ return this.serviceObject;
+ }
+
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceListener.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceListener.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/ApplicationServiceListener.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,68 @@
+/*
+ * $Header: /cvshome/build/org.osgi.application/src/org/osgi/application/ApplicationServiceListener.java,v 1.6 2006/07/12 21:21:34 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.application;
+
+import java.util.EventListener;
+
+import org.osgi.framework.*;
+
+/**
+ * An <code>ApplicationServiceEvent</code> listener. When a
+ * <code>ServiceEvent</code> is
+ * fired, it is converted to an <code>ApplictionServiceEvent</code>
+ * and it is synchronously delivered to an <code>ApplicationServiceListener</code>.
+ *
+ * <p>
+ * <code>ApplicationServiceListener</code> is a listener interface that may be
+ * implemented by an application developer.
+ * <p>
+ * An <code>ApplicationServiceListener</code> object is registered with the Framework
+ * using the <code>ApplicationContext.addServiceListener</code> method.
+ * <code>ApplicationServiceListener</code> objects are called with an
+ * <code>ApplicationServiceEvent</code> object when a service is registered, modified, or
+ * is in the process of unregistering.
+ *
+ * <p>
+ * <code>ApplicationServiceEvent</code> object delivery to
+ * <code>ApplicationServiceListener</code>
+ * objects is filtered by the filter specified when the listener was registered.
+ * If the Java Runtime Environment supports permissions, then additional
+ * filtering is done. <code>ApplicationServiceEvent</code> objects are only delivered to
+ * the listener if the application which defines the listener object's class has the
+ * appropriate <code>ServicePermission</code> to get the service using at
+ * least one of the named classes the service was registered under, and the application
+ * specified its dependece on the corresponding service in the application metadata.
+ *
+ * <p>
+ * <code>ApplicationServiceEvent</code> object delivery to <code>ApplicationServiceListener</code>
+ * objects is further filtered according to package sources as defined in
+ * {@link ServiceReference#isAssignableTo(Bundle, String)}.
+ *
+ * @version $Revision: 1.6 $
+ * @see ApplicationServiceEvent
+ * @see ServicePermission
+ */
+public interface ApplicationServiceListener extends EventListener {
+ /**
+ * Receives notification that a service has had a lifecycle change.
+ *
+ * @param event The <code>ApplicationServiceEvent</code> object.
+ */
+ public void serviceChanged(ApplicationServiceEvent event);
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/Framework.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/Framework.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/Framework.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/Framework.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,59 @@
+/*
+ * $Header: /cvshome/build/org.osgi.application/src/org/osgi/application/Framework.java,v 1.9 2006/07/11 13:19:02 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.application;
+
+import java.util.Hashtable;
+
+/**
+ * Using this class, OSGi-aware applications can obtain their {@link ApplicationContext}.
+ *
+ */
+public final class Framework {
+
+ private Framework() { }
+
+ private static Hashtable appContextHash;
+
+ /**
+ * This method needs an argument, an object that represents the application instance.
+ * An application consists of a set of object, however there is a single object, which
+ * is used by the corresponding application container to manage the lifecycle on the
+ * application instance. The lifetime of this object equals the lifetime of
+ * the application instance; therefore, it is suitable to represent the instance.
+ * <P>
+ * The returned {@link ApplicationContext} object is singleton for the
+ * specified application instance. Subsequent calls to this method with the same
+ * application instance must return the same context object
+ *
+ * @param applicationInstance is the activator object of an application instance
+ * @throws java.lang.NullPointerException If <code>applicationInstance</code>
+ * is <code>null</code>
+ * @throws java.lang.IllegalArgumentException if called with an object that is not
+ * the activator object of an application.
+ * @return the {@link ApplicationContext} of the specified application instance.
+ */
+ public static ApplicationContext getApplicationContext(Object applicationInstance) {
+ if( applicationInstance == null )
+ throw new NullPointerException( "Instance cannot be null!" );
+ ApplicationContext appContext = (ApplicationContext)appContextHash.get( applicationInstance );
+ if( appContext == null )
+ throw new IllegalArgumentException( "ApplicationContext not found!" );
+ return appContext;
+ }
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/package.html?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/package.html (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/package.html Wed Jan 30 08:46:24 2008
@@ -0,0 +1,10 @@
+<!-- $Header: /cvshome/build/org.osgi.application/src/org/osgi/application/package.html,v 1.2 2006/07/12 21:07:09 hargrave Exp $ -->
+<BODY>
+<p>Foreign Application Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.application; version=1.0
+</pre>
+</BODY>
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/application/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/application/packageinfo?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/application/packageinfo (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/application/packageinfo Wed Jan 30 08:46:24 2008
@@ -0,0 +1 @@
+version 1.0
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationAdminPermission.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationAdminPermission.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationAdminPermission.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationAdminPermission.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,407 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.application/src/org/osgi/service/application/ApplicationAdminPermission.java,v 1.34 2006/07/12 21:22:11 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.application;
+
+import java.security.Permission;
+import java.util.*;
+
+import org.osgi.framework.*;
+
+/**
+ * This class implements permissions for manipulating applications and
+ * their instances.
+ * <P>
+ * ApplicationAdminPermission can be targeted to applications that matches the
+ * specified filter.
+ * <P>
+ * ApplicationAdminPermission may be granted for different actions:
+ * <code>lifecycle</code>, <code>schedule</code> and <code>lock</code>.
+ * The permission <code>schedule</code> implies the permission
+ * <code>lifecycle</code>.
+ */
+public class ApplicationAdminPermission extends Permission {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Allows the lifecycle management of the target applications.
+ */
+ public static final String LIFECYCLE_ACTION = "lifecycle";
+
+ /**
+ * Allows scheduling of the target applications. The permission to
+ * schedule an application implies that the scheduler can also
+ * manage the lifecycle of that application i.e. <code>schedule</code>
+ * implies <code>lifecycle</code>
+ */
+ public static final String SCHEDULE_ACTION = "schedule";
+
+ /**
+ * Allows setting/unsetting the locking state of the target applications.
+ */
+ public static final String LOCK_ACTION = "lock";
+
+ private ApplicationDescriptor applicationDescriptor;
+
+ /**
+ * Constructs an ApplicationAdminPermission. The <code>filter</code>
+ * specifies the target application. The <code>filter</code> is an
+ * LDAP-style filter, the recognized properties are <code>signer</code>
+ * and <code>pid</code>. The pattern specified in the <code>signer</code>
+ * is matched with the Distinguished Name chain used to sign the application.
+ * Wildcards in a DN are not matched according to the filter string rules,
+ * but according to the rules defined for a DN chain. The attribute
+ * <code>pid</code> is matched with the PID of the application according to
+ * the filter string rules.
+ * <p>
+ * If the <code>filter</code> is <code>null</code> then it matches
+ * <code>"*"</code>. If
+ * <code>actions</code> is <code>"*"</code> then it identifies all the
+ * possible actions.
+ *
+ * @param filter
+ * filter to identify application. The value <code>null</code>
+ * is equivalent to <code>"*"</code> and it indicates "all application".
+ * @param actions
+ * comma-separated list of the desired actions granted on the
+ * applications or "*" means all the actions. It must not be
+ * <code>null</code>. The order of the actions in the list is
+ * not significant.
+ * @throws InvalidSyntaxException
+ * is thrown if the specified <code>filter</code> is not syntactically
+ * correct.
+ *
+ * @exception NullPointerException
+ * is thrown if the actions parameter is <code>null</code>
+ *
+ * @see ApplicationDescriptor
+ * @see org.osgi.framework.AdminPermission
+ */
+ public ApplicationAdminPermission(String filter, String actions) throws InvalidSyntaxException {
+ super(filter == null ? "*" : filter);
+
+ if( filter == null )
+ filter = "*";
+
+ if( actions == null )
+ throw new NullPointerException( "Action string cannot be null!" );
+
+ this.applicationDescriptor = null;
+ this.filter = (filter == null ? "*" : filter);
+ this.actions = actions;
+
+ if( !filter.equals( "*" ) && !filter.equals( "<<SELF>>" ) )
+ FrameworkUtil.createFilter( this.filter ); // check if the filter is valid
+ init();
+ }
+
+ /**
+ * This contructor should be used when creating <code>ApplicationAdminPermission</code>
+ * instance for <code>checkPermission</code> call.
+ * @param application the tareget of the operation, it must not be <code>null</code>
+ * @param actions the required operation. it must not be <code>null</code>
+ * @throws NullPointerException if any of the arguments is null.
+ */
+ public ApplicationAdminPermission(ApplicationDescriptor application, String actions) {
+ super(application.getApplicationId());
+
+ if( application == null || actions == null )
+ throw new NullPointerException( "ApplicationDescriptor and action string cannot be null!" );
+
+ this.filter = application.getApplicationId();
+ this.applicationDescriptor = application;
+ this.actions = actions;
+
+ init();
+ }
+
+ /**
+ * This method can be used in the {@link java.security.ProtectionDomain}
+ * implementation in the <code>implies</code> method to insert the
+ * application ID of the current application into the permission being
+ * checked. This enables the evaluation of the
+ * <code><<SELF>></code> pseudo targets.
+ * @param applicationId the ID of the current application.
+ * @return the permission updated with the ID of the current application
+ */
+ public ApplicationAdminPermission setCurrentApplicationId(String applicationId) {
+ ApplicationAdminPermission newPerm = null;
+
+ if( this.applicationDescriptor == null ) {
+ try {
+ newPerm = new ApplicationAdminPermission( this.filter, this.actions );
+ }catch( InvalidSyntaxException e ) {
+ throw new RuntimeException( "Internal error" ); /* this can never happen */
+ }
+ }
+ else
+ newPerm = new ApplicationAdminPermission( this.applicationDescriptor, this.actions );
+
+ newPerm.applicationID = applicationId;
+
+ return newPerm;
+ }
+
+ /**
+ * Checks if the specified <code>permission</code> is implied by this permission.
+ * The method returns true under the following conditions:
+ * <UL>
+ * <LI> This permission was created by specifying a filter (see {@link #ApplicationAdminPermission(String, String)})
+ * <LI> The implied <code>otherPermission</code> was created for a particular {@link ApplicationDescriptor}
+ * (see {@link #ApplicationAdminPermission(ApplicationDescriptor, String)})
+ * <LI> The <code>filter</code> of this permission mathes the <code>ApplicationDescriptor</code> specified
+ * in the <code>otherPermission</code>. If the filter in this permission is the
+ * <code><<SELF>></code> pseudo target, then the currentApplicationId set in the
+ * <code>otherPermission</code> is compared to the application Id of the target
+ * <code>ApplicationDescriptor</code>.
+ * <LI> The list of permitted actions in this permission contains all actions required in the
+ * <code>otherPermission</code>
+ * </UL>
+ * Otherwise the method returns false.
+ * @param otherPermission the implied permission
+ * @return true if this permission implies the <code>otherPermission</code>, false otherwise.
+ */
+ public boolean implies(Permission otherPermission) {
+ if( otherPermission == null )
+ return false;
+
+ if(!(otherPermission instanceof ApplicationAdminPermission))
+ return false;
+
+ ApplicationAdminPermission other = (ApplicationAdminPermission) otherPermission;
+
+ if( !filter.equals("*") ) {
+ if( other.applicationDescriptor == null )
+ return false;
+
+ if( filter.equals( "<<SELF>>") ) {
+ if( other.applicationID == null )
+ return false; /* it cannot be, this might be a bug */
+
+ if( !other.applicationID.equals( other.applicationDescriptor.getApplicationId() ) )
+ return false;
+ }
+ else {
+ Hashtable props = new Hashtable();
+ props.put( "pid", other.applicationDescriptor.getApplicationId() );
+ props.put( "signer", new SignerWrapper( other.applicationDescriptor ) );
+
+ Filter flt = getFilter();
+ if( flt == null )
+ return false;
+
+ if( !flt.match( props ) )
+ return false;
+ }
+ }
+
+ if( !actionsVector.containsAll( other.actionsVector ) )
+ return false;
+
+ return true;
+ }
+
+ public boolean equals(Object with) {
+ if( with == null || !(with instanceof ApplicationAdminPermission) )
+ return false;
+
+ ApplicationAdminPermission other = (ApplicationAdminPermission)with;
+
+ // Compare actions:
+ if( other.actionsVector.size() != actionsVector.size() )
+ return false;
+
+ for( int i=0; i != actionsVector.size(); i++ )
+ if( !other.actionsVector.contains( actionsVector.get( i ) ) )
+ return false;
+
+
+ return equal(this.filter, other.filter ) && equal(this.applicationDescriptor, other.applicationDescriptor)
+ && equal(this.applicationID, other.applicationID);
+ }
+
+ /**
+ * Compares parameters for equality. If both object are null, they are considered
+ * equal.
+ * @param a object to compare
+ * @param b other object to compare
+ * @return true if both objects are equal or both are null
+ */
+ private static boolean equal(Object a, Object b) {
+ // This equation is true if both references are null or both point
+ // to the same object. In both cases they are considered as equal.
+ if( a == b ) {
+ return true;
+ }
+
+ return a.equals(b);
+ }
+
+ public int hashCode() {
+ int hc = 0;
+ for( int i=0; i != actionsVector.size(); i++ )
+ hc ^= ((String)actionsVector.get( i )).hashCode();
+ hc ^= (null == this.filter )? 0 : this.filter.hashCode();
+ hc ^= (null == this.applicationDescriptor) ? 0 : this.applicationDescriptor.hashCode();
+ hc ^= (null == this.applicationID) ? 0 : this.applicationID.hashCode();
+ return hc;
+ }
+
+ /**
+ * Returns the actions of this permission.
+ * @return the actions specified when this permission was created
+ */
+ public String getActions() {
+ return actions;
+ }
+
+ private String applicationID;
+
+ private static final Vector ACTIONS = new Vector();
+ private Vector actionsVector;
+ private final String filter;
+ private final String actions;
+ private Filter appliedFilter = null;
+
+ static {
+ ACTIONS.add(LIFECYCLE_ACTION);
+ ACTIONS.add(SCHEDULE_ACTION);
+ ACTIONS.add(LOCK_ACTION);
+ }
+
+ private static Vector actionsVector(String actions) {
+ Vector v = new Vector();
+ StringTokenizer t = new StringTokenizer(actions.toUpperCase(), ",");
+ while (t.hasMoreTokens()) {
+ String action = t.nextToken().trim();
+ v.add(action.toLowerCase());
+ }
+
+ if( v.contains( SCHEDULE_ACTION ) && !v.contains( LIFECYCLE_ACTION ) )
+ v.add( LIFECYCLE_ACTION );
+
+ return v;
+ }
+
+
+ private static class SignerWrapper extends Object {
+ private String pattern;
+ private ApplicationDescriptor appDesc;
+
+ public SignerWrapper(String pattern) {
+ this.pattern = pattern;
+ }
+
+ SignerWrapper(ApplicationDescriptor appDesc) {
+ this.appDesc = appDesc;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof SignerWrapper))
+ return false;
+ SignerWrapper other = (SignerWrapper) o;
+ ApplicationDescriptor matchAppDesc = (ApplicationDescriptor) (appDesc != null ? appDesc : other.appDesc);
+ String matchPattern = appDesc != null ? other.pattern : pattern;
+ return matchAppDesc.matchDNChain(matchPattern);
+ }
+ }
+
+ private void init() {
+ actionsVector = actionsVector( actions );
+
+ if ( actions.equals("*") )
+ actionsVector = actionsVector( LIFECYCLE_ACTION + "," + SCHEDULE_ACTION + "," + LOCK_ACTION );
+ else if (!ACTIONS.containsAll(actionsVector))
+ throw new IllegalArgumentException("Illegal action!");
+
+ applicationID = null;
+ }
+
+ private Filter getFilter() {
+ String transformedFilter = filter;
+
+ if (appliedFilter == null) {
+ try {
+ int pos = filter.indexOf("signer"); //$NON-NLS-1$
+ if (pos != -1){
+
+ //there may be a signer attribute
+ StringBuffer filterBuf = new StringBuffer(filter);
+ int numAsteriskFound = 0; //use as offset to replace in buffer
+
+ int walkbackPos; //temp pos
+
+ //find occurences of (signer= and escape out *'s
+ while (pos != -1) {
+
+ //walk back and look for '(' to see if this is an attr
+ walkbackPos = pos-1;
+
+ //consume whitespace
+ while(walkbackPos >= 0 && Character.isWhitespace(filter.charAt(walkbackPos))) {
+ walkbackPos--;
+ }
+ if (walkbackPos <0) {
+ //filter is invalid - FilterImpl will throw error
+ break;
+ }
+
+ //check to see if we have unescaped '('
+ if (filter.charAt(walkbackPos) != '(' || (walkbackPos > 0 && filter.charAt(walkbackPos-1) == '\\')) {
+ //'(' was escaped or not there
+ pos = filter.indexOf("signer",pos+6); //$NON-NLS-1$
+ continue;
+ }
+ pos+=6; //skip over 'signer'
+
+ //found signer - consume whitespace before '='
+ while (Character.isWhitespace(filter.charAt(pos))) {
+ pos++;
+ }
+
+ //look for '='
+ if (filter.charAt(pos) != '=') {
+ //attr was signerx - keep looking
+ pos = filter.indexOf("signer",pos); //$NON-NLS-1$
+ continue;
+ }
+ pos++; //skip over '='
+
+ //found signer value - escape '*'s
+ while (!(filter.charAt(pos) == ')' && filter.charAt(pos-1) != '\\')) {
+ if (filter.charAt(pos) == '*') {
+ filterBuf.insert(pos+numAsteriskFound,'\\');
+ numAsteriskFound++;
+ }
+ pos++;
+ }
+
+ //end of signer value - look for more?
+ pos = filter.indexOf("signer",pos); //$NON-NLS-1$
+ } //end while (pos != -1)
+ transformedFilter = filterBuf.toString();
+ } //end if (pos != -1)
+
+ appliedFilter = FrameworkUtil.createFilter( transformedFilter );
+ } catch (InvalidSyntaxException e) {
+ //we will return null
+ }
+ }
+ return appliedFilter;
+ }
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationDescriptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationDescriptor.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationDescriptor.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationDescriptor.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,714 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.application/src/org/osgi/service/application/ApplicationDescriptor.java,v 1.61 2006/07/10 12:02:31 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.application;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.*;
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * An OSGi service that represents an installed application and stores
+ * information about it. The application descriptor can be used for instance
+ * creation.
+ */
+
+public abstract class ApplicationDescriptor {
+ /*
+ * NOTE: An implementor may also choose to replace this class in
+ * their distribution with a class that directly interfaces with the
+ * org.osgi.service.application implementation. This replacement class MUST NOT alter the
+ * public/protected signature of this class.
+ */
+
+ /**
+ * The property key for the localized name of the application.
+ */
+ public static final String APPLICATION_NAME = "application.name";
+
+ /**
+ * The property key for the localized icon of the application.
+ */
+ public static final String APPLICATION_ICON = "application.icon";
+
+ /**
+ * The property key for the unique identifier (PID) of the application.
+ */
+ public static final String APPLICATION_PID = Constants.SERVICE_PID;
+
+ /**
+ * The property key for the version of the application.
+ */
+ public static final String APPLICATION_VERSION = "application.version";
+
+ /**
+ * The property key for the name of the application vendor.
+ */
+ public static final String APPLICATION_VENDOR = Constants.SERVICE_VENDOR;
+
+
+ /**
+ * The property key for the visibility property of the application.
+ */
+ public static final String APPLICATION_VISIBLE = "application.visible";
+
+ /**
+ * The property key for the launchable property of the application.
+ */
+ public static final String APPLICATION_LAUNCHABLE = "application.launchable";
+
+ /**
+ * The property key for the locked property of the application.
+ */
+ public static final String APPLICATION_LOCKED = "application.locked";
+
+ /**
+ * The property key for the localized description of the application.
+ */
+ public static final String APPLICATION_DESCRIPTION = "application.description";
+
+ /**
+ * The property key for the localized documentation of the application.
+ */
+ public static final String APPLICATION_DOCUMENTATION = "application.documentation";
+
+ /**
+ * The property key for the localized copyright notice of the application.
+ */
+ public static final String APPLICATION_COPYRIGHT = "application.copyright";
+
+ /**
+ * The property key for the localized license of the application.
+ */
+ public static final String APPLICATION_LICENSE = "application.license";
+
+ /**
+ * The property key for the application container of the application.
+ */
+ public static final String APPLICATION_CONTAINER = "application.container";
+
+ /**
+ * The property key for the location of the application.
+ */
+ public static final String APPLICATION_LOCATION = "application.location";
+
+
+ private final String pid;
+
+
+ /**
+ * Constructs the <code>ApplicationDescriptor</code>.
+ *
+ * @param applicationId
+ * The identifier of the application. Its value is also available
+ * as the <code>service.pid</code> service property of this
+ * <code>ApplicationDescriptor</code> service. This parameter must not
+ * be <code>null</code>.
+ * @throws NullPointerException if the specified <code>applicationId</code> is null.
+ */
+ protected ApplicationDescriptor(String applicationId) {
+ if(null == applicationId ) {
+ throw new NullPointerException("Application ID must not be null!");
+ }
+
+ this.pid = applicationId;
+ try {
+ delegate = new Delegate();
+ delegate.setApplicationDescriptor( this, applicationId );
+ }
+ catch (Exception e) {
+ // Too bad ...
+ e.printStackTrace();
+ System.err
+ .println("No implementation available for ApplicationDescriptor, property is: "
+ + Delegate.cName);
+ }
+ }
+
+ /**
+ * Returns the identifier of the represented application.
+ *
+ * @return the identifier of the represented application
+ */
+ public final String getApplicationId() {
+ return pid;
+ }
+
+ /**
+ * This method verifies whether the specified <code>pattern</code>
+ * matches the Distinguished Names of any of the certificate chains
+ * used to authenticate this application.
+ * <P>
+ * The <code>pattern</code> must adhere to the
+ * syntax defined in {@link org.osgi.service.application.ApplicationAdminPermission}
+ * for signer attributes.
+ * <p>
+ * This method is used by {@link ApplicationAdminPermission#implies(java.security.Permission)} method
+ * to match target <code>ApplicationDescriptor</code> and filter.
+ *
+ * @param pattern a pattern for a chain of Distinguished Names. It must not be null.
+ * @return <code>true</code> if the specified pattern matches at least
+ * one of the certificate chains used to authenticate this application
+ * @throws NullPointerException if the specified <code>pattern</code> is null.
+ * @throws IllegalStateException if the application descriptor was
+ * unregistered
+ */
+ public abstract boolean matchDNChain( String pattern );
+
+ /**
+ * Returns the properties of the application descriptor as key-value pairs.
+ * The return value contains the locale aware and unaware properties as
+ * well. The returned <code>Map</code> will include the service
+ * properties of this <code>ApplicationDescriptor</code> as well.
+ * <p>
+ * This method will call the <code>getPropertiesSpecific</code> method
+ * to enable the container implementation to insert application model and/or
+ * container implementation specific properties.
+ * <P>
+ * The returned {@link java.util.Map} will contain the standard OSGi service
+ * properties as well
+ * (e.g. service.id, service.vendor etc.) and specialized application
+ * descriptors may offer further service properties. The returned Map contains
+ * a snapshot of the properties. It will not reflect further changes in the
+ * property values nor will the update of the Map change the corresponding
+ * service property.
+ *
+ * @param locale
+ * the locale string, it may be null, the value null means the
+ * default locale. If the provided locale is the empty String
+ * (<code>""</code>)then raw (non-localized) values are returned.
+ *
+ * @return copy of the service properties of this application descriptor service,
+ * according to the specified locale. If locale is null then the
+ * default locale's properties will be returned. (Since service
+ * properties are always exist it cannot return null.)
+ *
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ public final Map getProperties(String locale) {
+ Map props = getPropertiesSpecific( locale );
+
+ /* currently the ApplicationDescriptor manages the load/save of locking */
+ boolean isLocked = delegate.isLocked(); // the real locking state
+ Boolean containerLocked = (Boolean)props.remove( APPLICATION_LOCKED );
+ if( containerLocked != null && containerLocked.booleanValue() != isLocked ) {
+ try {
+ if( isLocked ) /* if the container's information is not correct */
+ lockSpecific(); /* about the locking state (after loading the lock states) */
+ else
+ unlockSpecific();
+ }catch( Exception e ) {}
+ }
+ /* replace the container's lock with the application model's lock, that's the correct */
+ props.put( APPLICATION_LOCKED, new Boolean( isLocked ) );
+ return props;
+ }
+
+ /**
+ * Container implementations can provide application model specific
+ * and/or container implementation specific properties via this
+ * method.
+ *
+ * Localizable properties must be returned localized if the provided
+ * <code>locale</code> argument is not the empty String. The value
+ * <code>null</code> indicates to use the default locale, for other
+ * values the specified locale should be used.
+ *
+ * The returned {@link java.util.Map} must contain the standard OSGi service
+ * properties as well
+ * (e.g. service.id, service.vendor etc.) and specialized application
+ * descriptors may offer further service properties.
+ * The returned <code>Map</code>
+ * contains a snapshot of the properties. It will not reflect further changes in the
+ * property values nor will the update of the Map change the corresponding
+ * service property.
+
+ * @param locale the locale to be used for localizing the properties.
+ * If <code>null</code> the default locale should be used. If it is
+ * the empty String (<code>""</code>) then raw (non-localized) values
+ * should be returned.
+ *
+ * @return the application model specific and/or container implementation
+ * specific properties of this application descriptor.
+ *
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ protected abstract Map getPropertiesSpecific(String locale);
+
+ /**
+ * Launches a new instance of an application. The <code>args</code> parameter specifies
+ * the startup parameters for the instance to be launched, it may be null.
+ * <p>
+ * The following steps are made:
+ * <UL>
+ * <LI>Check for the appropriate permission.
+ * <LI>Check the locking state of the application. If locked then return
+ * null otherwise continue.
+ * <LI>Calls the <code>launchSpecific()</code> method to create and start an application
+ * instance.
+ * <LI>Returns the <code>ApplicationHandle</code> returned by the
+ * launchSpecific()
+ * </UL>
+ * The caller has to have ApplicationAdminPermission(applicationPID,
+ * "launch") in order to be able to perform this operation.
+ * <P>
+ * The <code>Map</code> argument of the launch method contains startup
+ * arguments for the
+ * application. The keys used in the Map must be non-null, non-empty <code>String<code>
+ * objects. They can be standard or application
+ * specific. OSGi defines the <code>org.osgi.triggeringevent</code>
+ * key to be used to
+ * pass the triggering event to a scheduled application, however
+ * in the future it is possible that other well-known keys will be defined.
+ * To avoid unwanted clashes of keys, the following rules should be applied:
+ * <ul>
+ * <li>The keys starting with the dash (-) character are application
+ * specific, no well-known meaning should be associated with them.</li>
+ * <li>Well-known keys should follow the reverse domain name based naming.
+ * In particular, the keys standardized in OSGi should start with
+ * <code>org.osgi.</code>.</li>
+ * </ul>
+ * <P>
+ * The method is synchonous, it return only when the application instance was
+ * successfully started or the attempt to start it failed.
+ * <P>
+ * This method never returns <code>null</code>. If launching an application fails,
+ * the appropriate exception is thrown.
+ *
+ * @param arguments
+ * Arguments for the newly launched application, may be null
+ *
+ * @return the registered ApplicationHandle, which represents the newly
+ * launched application instance. Never returns <code>null</code>.
+ *
+ * @throws SecurityException
+ * if the caller doesn't have "lifecycle"
+ * ApplicationAdminPermission for the application.
+ * @throws ApplicationException
+ * if starting the application failed
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ * @throws IllegalArgumentException
+ * if the specified <code>Map</code> contains invalid keys
+ * (null objects, empty <code>String</code> or a key that is not
+ * <code>String</code>)
+ */
+ public final ApplicationHandle launch(Map arguments)
+ throws ApplicationException {
+ try {
+ delegate.launch(arguments);
+ }catch( SecurityException se ) {
+ isLaunchableSpecific(); /* check whether the bundle was uninstalled */
+ /* if yes, throws IllegalStateException */
+ throw se; /* otherwise throw the catched SecurityException */
+ }
+ if( !isLaunchableSpecific() )
+ throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE,
+ "Cannot launch the application!");
+ try {
+ return launchSpecific(arguments);
+ } catch(IllegalStateException ise) {
+ throw ise;
+ } catch(SecurityException se) {
+ throw se;
+ } catch( ApplicationException ae) {
+ throw ae;
+ } catch(Exception t) {
+ throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, t);
+ }
+ }
+
+ /**
+ * Called by launch() to create and start a new instance in an application
+ * model specific way. It also creates and registeres the application handle
+ * to represent the newly created and started instance and registeres it.
+ * The method is synchonous, it return only when the application instance was
+ * successfully started or the attempt to start it failed.
+ * <P>
+ * This method must not return <code>null</code>. If launching the application
+ * failed, and exception must be thrown.
+ *
+ * @param arguments
+ * the startup parameters of the new application instance, may be
+ * null
+ *
+ * @return the registered application model
+ * specific application handle for the newly created and started
+ * instance.
+ *
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ * @throws Exception
+ * if any problem occures.
+ */
+ protected abstract ApplicationHandle launchSpecific(Map arguments)
+ throws Exception;
+
+ /**
+ * This method is called by launch() to verify that according to the
+ * container, the application is launchable.
+ *
+ * @return true, if the application is launchable according to the
+ * container, false otherwise.
+ *
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ protected abstract boolean isLaunchableSpecific();
+
+ /**
+ * Schedules the application at a specified event. Schedule information
+ * should not get lost even if the framework or the device restarts so it
+ * should be stored in a persistent storage. The method registers a
+ * {@link ScheduledApplication} service in Service Registry, representing
+ * the created schedule.
+ * <p>
+ * The <code>Map</code> argument of the method contains startup
+ * arguments for the application. The keys used in the Map must be non-null,
+ * non-empty <code>String<code> objects.
+ * <p>
+ * The created schedules have a unique identifier within the scope of this
+ * <code>ApplicationDescriptor</code>. This identifier can be specified
+ * in the <code>scheduleId</code> argument. If this argument is <code>null</code>,
+ * the identifier is automatically generated.
+ *
+ * @param scheduleId
+ * the identifier of the created schedule. It can be <code>null</code>,
+ * in this case the identifier is automatically generated.
+ * @param arguments
+ * the startup arguments for the scheduled application, may be
+ * null
+ * @param topic
+ * specifies the topic of the triggering event, it may contain a
+ * trailing asterisk as wildcard, the empty string is treated as
+ * "*", must not be null
+ * @param eventFilter
+ * specifies and LDAP filter to filter on the properties of the
+ * triggering event, may be null
+ * @param recurring
+ * if the recurring parameter is false then the application will
+ * be launched only once, when the event firstly occurs. If the
+ * parameter is true then scheduling will take place for every
+ * event occurrence; i.e. it is a recurring schedule
+ *
+ * @return the registered scheduled application service
+ *
+ * @throws NullPointerException
+ * if the topic is <code>null</code>
+ * @throws InvalidSyntaxException
+ * if the specified <code>eventFilter</code> is not syntactically correct
+ * @throws ApplicationException
+ * if the schedule couldn't be created. The possible error
+ * codes are
+ * <ul>
+ * <li> {@link ApplicationException#APPLICATION_DUPLICATE_SCHEDULE_ID}
+ * if the specified <code>scheduleId</code> is already used
+ * for this <code>ApplicationDescriptor</code>
+ * <li> {@link ApplicationException#APPLICATION_SCHEDULING_FAILED}
+ * if the scheduling failed due to some internal reason
+ * (e.g. persistent storage error).
+ * </ul>
+ * @throws SecurityException
+ * if the caller doesn't have "schedule"
+ * ApplicationAdminPermission for the application.
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ * @throws IllegalArgumentException
+ * if the specified <code>Map</code> contains invalid keys
+ * (null objects, empty <code>String</code> or a key that is not
+ * <code>String</code>)
+ */
+ public final ScheduledApplication schedule(String scheduleId, Map arguments, String topic,
+ String eventFilter, boolean recurring) throws InvalidSyntaxException,
+ ApplicationException {
+ isLaunchableSpecific(); // checks if the ApplicationDescriptor was already unregistered
+ try {
+ return delegate.schedule(scheduleId, arguments, topic, eventFilter, recurring);
+ }catch( SecurityException se ) {
+ isLaunchableSpecific(); /* check whether the bundle was uninstalled */
+ /* if yes, throws IllegalStateException */
+ throw se; /* otherwise throw the catched SecurityException */
+ }
+ }
+
+ /**
+ * Sets the lock state of the application. If an application is locked then
+ * launching a new instance is not possible. It does not affect the already
+ * launched instances.
+ *
+ * @throws SecurityException
+ * if the caller doesn't have "lock" ApplicationAdminPermission
+ * for the application.
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ public final void lock() {
+ try {
+ delegate.lock();
+ }catch( SecurityException se ) {
+ isLaunchableSpecific(); /* check whether the bundle was uninstalled */
+ /* if yes, throws IllegalStateException */
+ throw se; /* otherwise throw the catched SecurityException */
+ }
+ lockSpecific();
+ }
+
+ /**
+ * This method is used to notify the container implementation that the
+ * corresponding application has been locked and it should update the
+ * <code>application.locked</code> service property accordingly.
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ protected abstract void lockSpecific();
+
+ /**
+ * Unsets the lock state of the application.
+ *
+ * @throws SecurityException
+ * if the caller doesn't have "lock" ApplicationAdminPermission
+ * for the application.
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ public final void unlock() {
+ try {
+ delegate.unlock();
+ }catch( SecurityException se ) {
+ isLaunchableSpecific(); /* check whether the bundle was uninstalled */
+ /* if yes, throws IllegalStateException */
+ throw se; /* otherwise throw the catched SecurityException */
+ }
+ unlockSpecific();
+ }
+
+ /**
+ * This method is used to notify the container implementation that the
+ * corresponding application has been unlocked and it should update the
+ * <code>application.locked</code> service property accordingly.
+
+ * @throws IllegalStateException
+ * if the application descriptor is unregistered
+ */
+ protected abstract void unlockSpecific();
+
+ Delegate delegate;
+ /**
+ * This class will load the class named
+ * by the org.osgi.vendor.application.ApplicationDescriptor and delegate
+ * method calls to an instance of the class.
+ */
+ static class Delegate {
+ static String cName;
+ static Class implementation;
+ static Method setApplicationDescriptor;
+ static Method isLocked;
+ static Method lock;
+ static Method unlock;
+ static Method schedule;
+ static Method launch;
+
+ static {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ cName = System.getProperty("org.osgi.vendor.application.ApplicationDescriptor");
+ if (cName == null) {
+ throw new NoClassDefFoundError("org.osgi.vendor.application.ApplicationDescriptor property must be set");
+ }
+
+ try {
+ implementation = Class.forName(cName);
+ }
+ catch (ClassNotFoundException e) {
+ throw new NoClassDefFoundError(e.toString());
+ }
+
+ try {
+ setApplicationDescriptor = implementation.getMethod("setApplicationDescriptor",
+ new Class[] {ApplicationDescriptor.class, String.class});
+ isLocked = implementation.getMethod("isLocked",
+ new Class[] {});
+ lock = implementation.getMethod("lock",
+ new Class[] {});
+ unlock = implementation.getMethod("unlock",
+ new Class[] {});
+ schedule = implementation.getMethod("schedule",
+ new Class[] {String.class, Map.class, String.class, String.class,
+ boolean.class});
+ launch = implementation.getMethod("launch",
+ new Class[] {Map.class});
+ }
+ catch (NoSuchMethodException e) {
+ throw new NoSuchMethodError(e.toString());
+ }
+
+ return null;
+ }
+ });
+ }
+
+ Object target;
+
+ Delegate() throws Exception {
+ target = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return implementation.newInstance();
+ }
+ });
+ }
+
+ void setApplicationDescriptor(ApplicationDescriptor d, String pid ) {
+ try {
+ try {
+ setApplicationDescriptor.invoke(target, new Object[] {d, pid});
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ boolean isLocked() {
+ try {
+ try {
+ return ((Boolean)isLocked.invoke(target, new Object[] {})).booleanValue();
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ void lock() {
+ try {
+ try {
+ lock.invoke(target, new Object[] {});
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ void unlock() {
+ try {
+ try {
+ unlock.invoke(target, new Object[] {});
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ ScheduledApplication schedule(String scheduleId, Map args, String topic, String filter,
+ boolean recurs) throws InvalidSyntaxException, ApplicationException {
+ try {
+ try {
+ return (ScheduledApplication)schedule.invoke(target, new Object[] {scheduleId, args, topic, filter,
+ new Boolean(recurs)});
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (InvalidSyntaxException e) {
+ throw e;
+ }
+ catch (ApplicationException e) {
+ throw e;
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ void launch(Map arguments) throws ApplicationException {
+ try {
+ try {
+ launch.invoke(target, new Object[] {arguments});
+ }
+ catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+ catch (ApplicationException e) {
+ throw e;
+ }
+ catch (Error e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationException.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationException.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationException.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/application/ApplicationException.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,136 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.application/src/org/osgi/service/application/ApplicationException.java,v 1.10 2006/07/10 11:49:12 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.application;
+
+/**
+ * This exception is used to indicate problems related to application
+ * lifecycle management.
+ *
+ * <code>ApplicationException</code> object is created by the Application Admin to denote
+ * an exception condition in the lifecycle of an application.
+ * <code>ApplicationException</code>s should not be created by developers.
+ * <br/>
+ * <code>ApplicationException</code>s are associated with an error code. This code
+ * describes the type of problem reported in this exception. The possible codes are:
+ * <ul>
+ * <li> {@link #APPLICATION_LOCKED} - The application couldn't be launched because it is locked.</li>
+ * <li> {@link #APPLICATION_NOT_LAUNCHABLE} - The application is not in launchable state.</li>
+ * <li> {@link #APPLICATION_INTERNAL_ERROR} - An exception was thrown by the application or its
+ * container during launch.</li>
+ * <li> {@link #APPLICATION_SCHEDULING_FAILED} - The scheduling of an application
+ * failed.
+ * </ul>
+ *
+ */
+public class ApplicationException extends Exception {
+ private static final long serialVersionUID = -7173190453622508207L;
+ private final Throwable cause;
+ private final int errorCode;
+
+ /**
+ * The application couldn't be launched because it is locked.
+ */
+ public static final int APPLICATION_LOCKED = 0x01;
+
+ /**
+ * The application is not in launchable state, it's
+ * {@link ApplicationDescriptor#APPLICATION_LAUNCHABLE}
+ * attribute is false.
+ */
+ public static final int APPLICATION_NOT_LAUNCHABLE = 0x02;
+
+ /**
+ * An exception was thrown by the application or the corresponding
+ * container during launch. The exception is available in {@link #getCause()}.
+ */
+ public static final int APPLICATION_INTERNAL_ERROR = 0x03;
+
+ /**
+ * The application schedule could not be created due to some internal error
+ * (for example, the schedule information couldn't be saved).
+ */
+ public static final int APPLICATION_SCHEDULING_FAILED = 0x04;
+
+ /**
+ * The application scheduling failed because the specified identifier
+ * is already in use.
+ */
+ public static final int APPLICATION_DUPLICATE_SCHEDULE_ID = 0x05;
+
+ /**
+ * Creates an <code>ApplicationException</code> with the specified error code.
+ * @param errorCode The code of the error
+ */
+ public ApplicationException(int errorCode) {
+ this(errorCode,(Throwable) null);
+ }
+
+ /**
+ * Creates a <code>ApplicationException</code> that wraps another exception.
+ *
+ * @param errorCode The code of the error
+ * @param cause The cause of this exception.
+ */
+ public ApplicationException(int errorCode, Throwable cause) {
+ super();
+ this.cause = cause;
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Creates an <code>ApplicationException</code> with the specified error code.
+ * @param errorCode The code of the error
+ * @param message The associated message
+ */
+ public ApplicationException(int errorCode, String message) {
+ this(errorCode, message,null);
+ }
+
+ /**
+ * Creates a <code>ApplicationException</code> that wraps another exception.
+ *
+ * @param errorCode The code of the error
+ * @param message The associated message.
+ * @param cause The cause of this exception.
+ */
+ public ApplicationException(int errorCode, String message, Throwable cause) {
+ super(message);
+ this.cause = cause;
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Returns the cause of this exception or <code>null</code> if no cause
+ * was specified when this exception was created.
+ *
+ * @return The cause of this exception or <code>null</code> if no cause
+ * was specified.
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the error code associcated with this exception.
+ * @return The error code of this exception.
+ */
+ public int getErrorCode() {
+ return errorCode;
+ }
+}