diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppPersistence.java')
-rw-r--r-- | bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppPersistence.java | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppPersistence.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppPersistence.java deleted file mode 100644 index 055ea77b3..000000000 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppPersistence.java +++ /dev/null @@ -1,430 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. - * 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: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.equinox.internal.app; - -import java.io.*; -import java.util.*; -import org.eclipse.osgi.framework.log.FrameworkLogEntry; -import org.eclipse.osgi.service.datalocation.Location; -import org.eclipse.osgi.storagemanager.StorageManager; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.*; -import org.osgi.service.application.*; -import org.osgi.service.event.Event; -import org.osgi.service.event.EventConstants; -import org.osgi.util.tracker.ServiceTracker; -import org.osgi.util.tracker.ServiceTrackerCustomizer; - -/** - * Manages all persistent data for ApplicationDescriptors (lock status, - * scheduled applications etc.) - */ -public class AppPersistence implements ServiceTrackerCustomizer { - private static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$ - - private static final String FILTER_PREFIX = "(&(objectClass=org.eclipse.osgi.service.datalocation.Location)(type="; //$NON-NLS-1$ - private static final String FILE_APPLOCKS = ".locks"; //$NON-NLS-1$ - private static final String FILE_APPSCHEDULED = ".scheduled"; //$NON-NLS-1$ - private static final String EVENT_HANDLER = "org.osgi.service.event.EventHandler"; //$NON-NLS-1$ - - private static final int DATA_VERSION = 2; - private static final byte NULL = 0; - private static final int OBJECT = 1; - - private static BundleContext context; - private static ServiceTracker configTracker; - private static Location configLocation; - private static Collection locks = new ArrayList(); - private static Map scheduledApps = new HashMap(); - static ArrayList timerApps = new ArrayList(); - private static StorageManager storageManager; - private static boolean scheduling = false; - static boolean shutdown = false; - private static int nextScheduledID = 1; - private static Thread timerThread; - - static void start(BundleContext bc) { - context = bc; - shutdown = false; - initConfiguration(); - } - - static void stop() { - shutdown = true; - stopTimer(); - if (storageManager != null) { - storageManager.close(); - storageManager = null; - } - closeConfiguration(); - context = null; - } - - private static void initConfiguration() { - closeConfiguration(); // just incase - Filter filter = null; - try { - filter = context.createFilter(FILTER_PREFIX + PROP_CONFIG_AREA + "))"); //$NON-NLS-1$ - } catch (InvalidSyntaxException e) { - // ignore this. It should never happen as we have tested the above format. - } - configTracker = new ServiceTracker(context, filter, new AppPersistence()); - configTracker.open(); - } - - private static void closeConfiguration() { - if (configTracker != null) - configTracker.close(); - configTracker = null; - } - - /** - * Used by {@link ApplicationDescriptor} to determine if an application is locked. - * @param desc the application descriptor - * @return true if the application is persistently locked. - */ - public static boolean isLocked(ApplicationDescriptor desc) { - synchronized (locks) { - return locks.contains(desc.getApplicationId()); - } - } - - /** - * Used by {@link ApplicationDescriptor} to determine lock and unlock and application. - * @param desc the application descriptor - * @param locked the locked flag - */ - public static void saveLock(ApplicationDescriptor desc, boolean locked) { - synchronized (locks) { - if (locked) { - if (!locks.contains(desc.getApplicationId())) { - locks.add(desc.getApplicationId()); - saveData(FILE_APPLOCKS); - } - } else if (locks.remove(desc.getApplicationId())) { - saveData(FILE_APPLOCKS); - } - } - } - - static void removeScheduledApp(EclipseScheduledApplication scheduledApp) { - boolean removed; - synchronized (scheduledApps) { - removed = scheduledApps.remove(scheduledApp.getScheduleId()) != null; - if (removed) { - saveData(FILE_APPSCHEDULED); - } - } - if (removed) - synchronized (timerApps) { - timerApps.remove(scheduledApp); - } - } - - /** - * Used by {@link ScheduledApplication} to persistently schedule an application launch - * @param descriptor - * @param arguments - * @param topic - * @param eventFilter - * @param recurring - * @return the scheduled application - * @throws InvalidSyntaxException - * @throws ApplicationException - */ - public static ScheduledApplication addScheduledApp(ApplicationDescriptor descriptor, String scheduleId, Map arguments, String topic, String eventFilter, boolean recurring) throws InvalidSyntaxException, ApplicationException { - if (!scheduling && !checkSchedulingSupport()) - throw new ApplicationException(ApplicationException.APPLICATION_SCHEDULING_FAILED, "Cannot support scheduling without org.osgi.service.event package"); //$NON-NLS-1$ - // check the event filter for correct syntax - context.createFilter(eventFilter); - EclipseScheduledApplication result; - synchronized (scheduledApps) { - result = new EclipseScheduledApplication(context, getNextScheduledID(scheduleId), descriptor.getApplicationId(), arguments, topic, eventFilter, recurring); - addScheduledApp(result); - saveData(FILE_APPSCHEDULED); - } - return result; - } - - // must call this method while holding the scheduledApps lock - private static void addScheduledApp(EclipseScheduledApplication scheduledApp) { - if (ScheduledApplication.TIMER_TOPIC.equals(scheduledApp.getTopic())) { - synchronized (timerApps) { - timerApps.add(scheduledApp); - if (timerThread == null) - startTimer(); - } - } - scheduledApps.put(scheduledApp.getScheduleId(), scheduledApp); - Hashtable serviceProps = new Hashtable(); - if (scheduledApp.getTopic() != null) - serviceProps.put(EventConstants.EVENT_TOPIC, new String[] {scheduledApp.getTopic()}); - if (scheduledApp.getEventFilter() != null) - serviceProps.put(EventConstants.EVENT_FILTER, scheduledApp.getEventFilter()); - serviceProps.put(ScheduledApplication.SCHEDULE_ID, scheduledApp.getScheduleId()); - serviceProps.put(ScheduledApplication.APPLICATION_PID, scheduledApp.getAppPid()); - ServiceRegistration sr = context.registerService(new String[] {ScheduledApplication.class.getName(), EVENT_HANDLER}, scheduledApp, serviceProps); - scheduledApp.setServiceRegistration(sr); - } - - private static String getNextScheduledID(String scheduledId) throws ApplicationException { - if (scheduledId != null) { - if (scheduledApps.get(scheduledId) != null) - throw new ApplicationException(ApplicationException.APPLICATION_DUPLICATE_SCHEDULE_ID, "Duplicate scheduled ID: " + scheduledId); //$NON-NLS-1$ - return scheduledId; - } - if (nextScheduledID == Integer.MAX_VALUE) - nextScheduledID = 0; - String result = new Integer(nextScheduledID++).toString(); - while (scheduledApps.get(result) != null && nextScheduledID < Integer.MAX_VALUE) - result = new Integer(nextScheduledID++).toString(); - if (nextScheduledID == Integer.MAX_VALUE) - throw new ApplicationException(ApplicationException.APPLICATION_DUPLICATE_SCHEDULE_ID, "Maximum number of scheduled applications reached"); //$NON-NLS-1$ - return result; - } - - private static boolean checkSchedulingSupport() { - // cannot support scheduling without the event admin package - try { - Class.forName(EVENT_HANDLER); - scheduling = true; - return true; - } catch (ClassNotFoundException e) { - scheduling = false; - return false; - } - } - - private synchronized static boolean loadData(String fileName) { - try { - Location location = configLocation; - if (location == null) - return false; - File theStorageDir = new File(location.getURL().getPath() + '/' + Activator.PI_APP); - if (storageManager == null) { - boolean readOnly = location.isReadOnly(); - storageManager = new StorageManager(theStorageDir, readOnly ? "none" : null, readOnly); //$NON-NLS-1$ - storageManager.open(!readOnly); - } - File dataFile = storageManager.lookup(fileName, false); - if (dataFile == null || !dataFile.isFile()) { - Location parent = location.getParentLocation(); - if (parent != null) { - theStorageDir = new File(parent.getURL().getPath() + '/' + Activator.PI_APP); - StorageManager tmp = new StorageManager(theStorageDir, "none", true); //$NON-NLS-1$ - tmp.open(false); - dataFile = tmp.lookup(fileName, false); - tmp.close(); - } - } - if (dataFile == null || !dataFile.isFile()) - return true; - if (FILE_APPLOCKS.equals(fileName)) - loadLocks(dataFile); - else if (FILE_APPSCHEDULED.equals(fileName)) - loadSchedules(dataFile); - } catch (IOException e) { - return false; - } - return true; - } - - private static void loadLocks(File locksData) throws IOException { - ObjectInputStream in = null; - try { - in = new ObjectInputStream(new FileInputStream(locksData)); - int dataVersion = in.readInt(); - if (dataVersion != DATA_VERSION) - return; - int numLocks = in.readInt(); - synchronized (locks) { - for (int i = 0; i < numLocks; i++) - locks.add(in.readUTF()); - } - } finally { - if (in != null) - in.close(); - } - } - - private static void loadSchedules(File schedulesData) throws IOException { - ObjectInputStream in = null; - try { - in = new ObjectInputStream(new FileInputStream(schedulesData)); - int dataVersion = in.readInt(); - if (dataVersion != DATA_VERSION) - return; - int numScheds = in.readInt(); - for (int i = 0; i < numScheds; i++) { - String id = readString(in, false); - String appPid = readString(in, false); - String topic = readString(in, false); - String eventFilter = readString(in, false); - boolean recurring = in.readBoolean(); - Map args = (Map) in.readObject(); - EclipseScheduledApplication schedApp = new EclipseScheduledApplication(context, id, appPid, args, topic, eventFilter, recurring); - addScheduledApp(schedApp); - } - } catch (InvalidSyntaxException e) { - throw new IOException(e.getMessage()); - } catch (NoClassDefFoundError e) { - throw new IOException(e.getMessage()); - } catch (ClassNotFoundException e) { - throw new IOException(e.getMessage()); - } finally { - if (in != null) - in.close(); - } - } - - private synchronized static void saveData(String fileName) { - if (storageManager == null || storageManager.isReadOnly()) - return; - try { - File data = storageManager.createTempFile(fileName); - if (FILE_APPLOCKS.equals(fileName)) - saveLocks(data); - else if (FILE_APPSCHEDULED.equals(fileName)) - saveSchedules(data); - storageManager.lookup(fileName, true); - storageManager.update(new String[] {fileName}, new String[] {data.getName()}); - } catch (IOException e) { - Activator.log(new FrameworkLogEntry(Activator.PI_APP, FrameworkLogEntry.ERROR, 0, NLS.bind(Messages.persistence_error_saving, fileName), 0, e, null)); - } - } - - // must call this while holding the locks lock - private static void saveLocks(File locksData) throws IOException { - ObjectOutputStream out = null; - try { - out = new ObjectOutputStream(new FileOutputStream(locksData)); - out.writeInt(DATA_VERSION); - out.writeInt(locks.size()); - for (Iterator iterLocks = locks.iterator(); iterLocks.hasNext();) - out.writeUTF((String) iterLocks.next()); - } finally { - if (out != null) - out.close(); - } - } - - // must call this while holding the scheduledApps lock - private static void saveSchedules(File schedulesData) throws IOException { - ObjectOutputStream out = null; - try { - out = new ObjectOutputStream(new FileOutputStream(schedulesData)); - out.writeInt(DATA_VERSION); - out.writeInt(scheduledApps.size()); - for (Iterator apps = scheduledApps.values().iterator(); apps.hasNext();) { - EclipseScheduledApplication app = (EclipseScheduledApplication) apps.next(); - writeStringOrNull(out, app.getScheduleId()); - writeStringOrNull(out, app.getAppPid()); - writeStringOrNull(out, app.getTopic()); - writeStringOrNull(out, app.getEventFilter()); - out.writeBoolean(app.isRecurring()); - out.writeObject(app.getArguments()); - } - } finally { - if (out != null) - out.close(); - } - } - - private static void startTimer() { - timerThread = new Thread(new AppTimer(), "app schedule timer"); //$NON-NLS-1$ - timerThread.start(); - } - - private static void stopTimer() { - if (timerThread != null) - timerThread.interrupt(); - timerThread = null; - } - - static class AppTimer implements Runnable { - public void run() { - int lastMin = -1; - while (!shutdown) { - try { - Thread.sleep(30000); // sleeping 30 secs instead of 60 to try to avoid skipping minutes - Calendar cal = Calendar.getInstance(); - int minute = cal.get(Calendar.MINUTE); - if (minute == lastMin) - continue; - lastMin = minute; - Hashtable props = new Hashtable(); - props.put(ScheduledApplication.YEAR, new Integer(cal.get(Calendar.YEAR))); - props.put(ScheduledApplication.MONTH, new Integer(cal.get(Calendar.MONTH))); - props.put(ScheduledApplication.DAY_OF_MONTH, new Integer(cal.get(Calendar.DAY_OF_MONTH))); - props.put(ScheduledApplication.DAY_OF_WEEK, new Integer(cal.get(Calendar.DAY_OF_WEEK))); - props.put(ScheduledApplication.HOUR_OF_DAY, new Integer(cal.get(Calendar.HOUR_OF_DAY))); - props.put(ScheduledApplication.MINUTE, new Integer(minute)); - Event timerEvent = new Event(ScheduledApplication.TIMER_TOPIC, (Dictionary) props); - EclipseScheduledApplication[] apps = null; - // poor mans implementation of dispatching events; the spec will not allow us to use event admin to dispatch the virtual timer events; boo!! - synchronized (timerApps) { - if (timerApps.size() == 0) - continue; - apps = (EclipseScheduledApplication[]) timerApps.toArray(new EclipseScheduledApplication[timerApps.size()]); - } - for (int i = 0; i < apps.length; i++) { - try { - String filterString = apps[i].getEventFilter(); - Filter filter = filterString == null ? null : FrameworkUtil.createFilter(filterString); - if (filter == null || filter.match(props)) - apps[i].handleEvent(timerEvent); - } catch (Throwable t) { - String message = NLS.bind(Messages.scheduled_app_launch_error, apps[i].getAppPid()); - Activator.log(new FrameworkLogEntry(Activator.PI_APP, FrameworkLogEntry.WARNING, 0, message, 0, t, null)); - } - } - } catch (InterruptedException e) { - // do nothing; - } - } - } - } - - private static String readString(ObjectInputStream in, boolean intern) throws IOException { - byte type = in.readByte(); - if (type == NULL) - return null; - return intern ? in.readUTF().intern() : in.readUTF(); - } - - private static void writeStringOrNull(ObjectOutputStream out, String string) throws IOException { - if (string == null) - out.writeByte(NULL); - else { - out.writeByte(OBJECT); - out.writeUTF(string); - } - } - - public Object addingService(ServiceReference reference) { - if (configLocation != null) - return null; // only care about one configuration - configLocation = (Location) context.getService(reference); - loadData(FILE_APPLOCKS); - loadData(FILE_APPSCHEDULED); - return configLocation; - } - - public void modifiedService(ServiceReference reference, Object service) { - // don't care - } - - public void removedService(ServiceReference reference, Object service) { - if (service == configLocation) - configLocation = null; - } -} |